In a previous story, we created a simple web application leveraging a micro-frontend architecture. Now it is time to deploy our app to the cloud. This story - Part 2 - is going to be “AWS-heavy”, as we deep dive into various AWS resources and services. The end result will be the deployment of the web app to AWS, which you can access from your machine.

Goal

We want to design and deploy below architecture by focusing on two areas:

Excited? I am!

Overall Web App architecture

Prerequisites

In order to follow through, you should at least create or have access to a free AWS Account via the AWS Console. Basic AWS knowledge is recommended, thought I will keep things simple and give you some reference. As a rule of thumb, I recommend below basic security and cost-saving best practices:

You should be ready now to start this journey. Now, before we can deploy our web-apps, let’s briefly introduce Amplify.

Introduction to AWS Amplify

AWS Amplify is a framework allowing to connect your web or mobile app to AWS Cloud resources, providing CLIs, libraries and UI components. Simply put, it creates AWS resources and links them with your project by exposing a set of services which can be configured (added) to your frontend application. Some examples are authentication (Cognito), hosting (S3 + CloudFront), api (REST or GraphQL) and much more.

We will rely heavily on CLI, which will ask you to answer some simple questions in order to generate the needed AWS resources to deploy your backend services. Do not worry, we will go through this together in the next section, where we will understand two very important Amplify commands, configure and init.

Amplify configure command

To get started with Amplify we need to install and configure the CLI on your local machine, with below one-time step commands:

npm i -g @aws-amplify/cli
amplify configure

Configure command links your local machine Amplify setup with your AWS account. You will be asked to sign-in in your AWS account and to create an IAM user. In our example we will name it amplify-micro-frontends-playground. See below animation for detailed steps:

Steps to create an IAM user.
Steps to create an IAM user.
Steps to create an IAM user during Amplify configure

Once IAM user is created, take notes of users’ access key and secret access key (store them carefully), add them to the prompt and proceed with setup. Among others, you need to create or reuse an existing local AWS profile. You can find it under your user directory in~/.aws/config and ~/.aws/credentials files. In my case I just reused my existing default profile. If everything went smooth, you should end up with similar screen:

Execution of amplify configure command
Execution of amplify configure command
Execution of amplify configure command

Good stuff! Now we can start integrating Amplify to our micro-frontends web app by initializing it with real AWS resources.

Amplify init command

Now it is time to link your frontend application with AWS Amplify in order to provision resources where we will deploy the app:

cd mfe-parent
amplify init

The command will ask you a few questions aiming at linking your current project with an Amplify configuration, if in doubt consult documentation. You should end up with a screen as below:

Execution of amplify init command on parent application.
Execution of amplify init command on parent application.
Execution of amplify init command on parent application

Now that command got executed, let’s understand what has just happened:

  • A new Amplify app, which contains an overview of all Amplify backends we are going to install, has been created in AWS Console.
Amplify apps in AWS Console
  • A newly deployed CloudFormation stack got created. Cloud Formation is a AWS service enabling infrastructure as code, the process of managing and automate the provision of AWS resources by defining them through a template and foster software development best practices in the operational/devops ecosystem, e.g. code versioning and pull requests. In our case, Amplify generated a CloudFormation stack (a collection of AWS resources manageable as a single unit), which provisioned an S3 deployment bucket containing Amplify metadata files (well explained here) and a couple of IAM roles (Auth & Unauth) which will be used later once we start adding AWS resources to our amplify configuration.
Cloud Formation stack for amplify init
  • A new amplify folder got created under frontend project. This includes a number of project metadata that glue your frontend configuration with Amplify remove configuration. Just a note about the backend-config.json file, which contains a description of all the resources you have created and installed with Amplify. You can deep dive here to details of all files.
Generated Amplify folders in root module
  • Last but not least. Notice we mentioned the package.json’s build script. This is important as Amplify will use that command to deploy the static content to another S3 when we will publish changes in CloudFront (coming soon).

At this point we have set foundation for our frontend project. Let’s now achieve our goal by deployment the micro-frontends to the cloud and protecting the app with a login screen.

Deploy micro-frontends

It is now finally time to deploy our micro-frontends. Typically, the de-facto place in AWS to deploy static content as images, JavaScript files and HTML pages is AWS Simple Cloud Storage (S3) (happy 15th anniversary!), a scalable object storage service. Moreover, to optimize applications performance and security, a common pattern is to set a Content Delivery Network in front of S3. Of course, AWS has the perfect partner in crime for that, which is Amazon CloudFront. It is not difficult to set this small architecture manually, but it may be time consuming for front end teams, or generally teams not familiar with cloud and/or AWS. Also we want to avoid repetition and have teams focusing on business logic, not on deploy pipeline every time they code. That is how Amplify comes in help: to boost deployment time and easiness of usage. Let’s assume we, as Core Team, need to deploy our own independent module to AWS. To do that, within the mfe-parent module, let’s execute the following command:

amplify add hosting

A lot happened behind the scenes. I chose the deployment to be based on S3 and CloudFront using HTTPS, because it mimics a real production setup. You should get a final result as below:

Execution of add hosting command

You will also notice that a new folder was created with the name hosting under the amplify/backend folder. It contains a CloudFormation template which basically instructs AWS to provision an S3 bucket which can be only accessed through CloudFront distribution, by creating a CloudFront Origin Access Identity (OAI). This is beautiful, as we are leveraging infrastructure as code to make this process consistent, automatic, with reduced error-rate across teams and pipelines. As this is fully automated and handled by Amplify, we just now to publish those changes:

amplify publish

This is pretty cool. Apart from provisioning S3 buckets and CloudFront distributions, Amplify has built your project (using the npm run build script provided during amplify init command) and added the generated bundle and static data into S3. Below picture gives a bit of overview on how S3, CloudFront and its integrations (OAI and IAM) are now available.

Cloud Formation for hosting command

Repeat for accounts and payments

Now repeat both the init, hosting and publish commands for both accounts and payments module. If everything is in place, you should end up with:

  • 6 S3 buckets (3 Amplify deployments + 3 buckets containing files from build process)
Provisioned AWS resources after publish hosting command

Login feature

Now it is time to protect our web app by introducing a login screen. To do that, we will use Amplify to leverage Amazon Cognito User Pools. Let’s execute below command inside mfe-parent micro-frontend.

amplify add auth

The command generated a CloudFormation template under the amplify/auth folder, which, as done with previous hosting command, glues your local Amplify project with real AWS resources. Authentication with Amplify is based on Cognito User Pools, a user directory which allows us to create users who can sign in to our app. Let’s publish those changes to the cloud.

amplify publish

A lot of resources have been allocated via CloudFormation template. Below generated AWS resources make sure that your local Amplify profile is linked and authorized to access Cognito user and identity pools which relies on lambda functions and IAM roles and policies to do that.

Cloud Formation for add auth command

Now that all AWS resources have been provisioned — and for the scope of our proof of concept — we can create any users who can access the web app. As shown below, let’s create guest /awsguest credentials which you can use later to access the web app.

Add new user in Cognito User Pools

Next question is how does user log in to our app. For that, we need to introduce a login screen to the React parent/shell app. We can achieve this by installing a React UI component made available by AWS amplify React library package. To do so, install the package as shown below:

npm install aws-amplify @aws-amplify/ui-react  — save

Now we need to modify our App.js of mfe-parent app in order to use the component. We will leverage an Amplify UI Component for React, which exposes a set of components to mimic a login screen, as it is a pretty common scenario. The most minimal usage is to reuse the withAuthentication high order component to wrap the App and get an off-shelf implementation of a login, as shown in this article. In my case, I played a bit more both to learn its internals but also because I wanted to disable the sign up button which comes from default behavior of withAuthentication. Thus, my implementation looks like below:

React’s App.js main file.

Above snippet uses Amplify UI Components to display a login screen, without the sign in option. We hooked into the onAuthUIStateChange method in order to know whether we have signed in or not. In successful case, we show our content’s app.

If you now start the parent app, you should see a login screen like this:

Amplify React UI-based login screen.
Amplify React UI-based login screen.
Amplify React UI-based login screen.

Finally, to move your code to the S3 and CloudFront distribution, just publish:

amplify publish

One last step is to update your index.html file to reference the Cloudfront urls instead of your localhost bundles. You can find those urls on CloudFront distribution configurations.

We are done! Our micro-frontends architecture is now deployed on the cloud.

Web app deployed on AWS Cloud

Summary

In Part 1 we demonstrated how is possible to leverage Web Components to create a micro-frontend web architecture based on Angular and React apps. Part 2 focused on deploying our app via Amplify, which, as demonstrated above, abstracts quite a bit of heavy-lifting internals and resource provisioning from frontend developers and allow them to deploy their app in minutes. Topic is big and this story just shows off a glimpse of all capabilities and creativity that AWS continuously fosters. There is always room for improvements and demo about:

Hope this story gave you a sense of how above topics could be relevant in your organization and provoked your mind to try things out ;)

You can access the live demo here (guest/awsguest credentials), and I strongly suggest to go through this tutorial, try it your self, learn and have fun. Code can be found on Github. Thanks for the read and see you in next stories!

AWS Gotchas

Resources

Tech Lead with a passion for frontend, backend and cloud

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store