Briebug Blog

Sharing our thoughts with the community

Getting Started With Micro FrontEnds and Angular

Getting Started With Micro FrontEnds and Angular


Micro Frontends (MFE) are the idea that a Single Page Application (SPA) can be divided into separate specialized sections that give independent teams end-to-end ownership. This gives development teams the autonomy to complete their work independently.


Choosing Micro Frontends implementation is a decision that needs to be evaluated carefully to ensure it meets organizational needs. Some of the benefits of Micro Frontends include:


  • The use of different frameworks or UI libraries for each frontend to meet the team's needs or if the team inherited a codebase that needs to be incorporated into an existing application.
  • Independent deployments as each frontend can be deployed independently of the rest of the application.
  • Allows the development team(s) to scale as each team will be working independently of the rest of the team(s).


These are awesome benefits for large development teams that work on an Enterprise size application. Micro Frontends also has some limitations:


  • Complexity: adding different frameworks and having the ability to share code between frontend(s) can increase the complexity for onboarding new team members.
  • Operational complexity: deployment to production can be complicated as each frontend needs to be deployed independently and the container application needs to be updated and its release coordinated between different teams.
  • Larger application bundles: with different frameworks and possibly code duplication between different frontend(s) this can impact the performance of the application.

Tools

In this article we are going to focus on setting up an Angular Micro Frontends project using the following tools:


  • Micro Frontends and Angular work through the Module Federation feature of Webpack 5. Webpack 5 was introduced as a breaking change in Angular 12.
  • The @angular-architects/module-federation by Manfred Steyer can be added to any Angular project via schematics. This package is also used within Nx tooling.
  • New Nx tooling generates the configuration needed for Micro Frontends by using the @nrwl/angular:setup-mfe schematic.

Theory

Before we begin our implementation let's define some concepts about Micro Frontends:


  • host : This is the project that displays the remote(s). You want to consider the host as the shell for the application responsible for coordinating the remote(s).
  • remote : This is part of the application, not the entire application, that will be displayed by the host. In theory, this can be framework agnostic. In this article we will be using Angular only. A Micro FrontEnd project will contain only one host, but multiple remotes.
  • Micro FrontEnd Framework : This is the framework that sits between the host and remote(s) to coordinate loading and unloading of remotes. In our case this is Webpack 5 Module Federation. We will not be discussing the details of how Module Federation works as it is beyond the scope of this article.

Implementation

In this article we are going to show you how to setup Micro Frontends project with both Nx Workspace and Angular CLI. We will be utilizing schematics throughout the article.

Using Nx Workspace

We begin our implementation by creating a new Nx workspace and call it microFrontEnds using the following command:

Follow the interactive prompts and create an Angular application called shell, which will be the host in our application.

We will use the new schematics later to add the needed configuration for Micro Frontends.

Adding Angular Applications

At this time we need to add new Angular application(s) that will serve as the parts that we want to slice our application into, and these will be the remotes in our setup. In our example we will create 2 applications: one is called dashboard, which will serve as our home page. And another called admin, which will be worked on by a different team. We will use the following command:

Up to this point we have utilized typical commands and have not configured anything related to Micro Frontends. What we have at this point is a standard monorepo with 3 Angular applications.

Setup the host

At this time we need to begin configuring our shell and set it up as our host. We can issue the following command:

The parameters we pass to this schematic according to Nx documentation:


  • appName : The name of the application to generate the Module Federation configuration for.
  • mfeType : The type of application to generate the Module Federation configuration for. Possible options are host or remote.
  • port : The port at which the application should be served.
  • routing : Generate a routing setup to allow a host application to route to the remote application.

After we run this command we will have 3 new files and updates to existing files. These changes include:

  • main.ts : This file has been changed and its entire content is moved to a newly created file called bootstrap, which we will discuss next, and it is replaced with an import statement for the newly created bootstrap file.

  • bootstrap.ts : This file contains the original contents of the main.ts file without any changes. The reason this file is needed is to ensure the modules are exposed correctly by Webpack. The Webpack process is divided into 2 steps: one step is asynchronous while the other is synchronous. The low level details of how Webpack handles Module Federation is beyond the scope of this article.

  • webpack.config.js & webpack.prod.config.js : This is where the magic happens. This file brings in the packages needed and includes a modified Webpack configuration. There are 2 sections we need to be aware off. sharedMappings is where you can include any shared library or components. plugins is where you list remotes and any framework packages to share, as you can see from the code section below.
  • package.json : The schematic adds @angular-architects/module-federation package and installs it.

  • angular.json : The schematic makes multiple changes to this file including changing the builder on the shell project for both the build and serve commands, adding the appropriate Webpack config file and port to the build and serve commands, and adding a new serve-mfe command.

At this point our shell setup is complete and ready to accept remotes.

Setup the remote(s)

We will issue 2 very similar commands to setup our shell in the previous section. The first command we issue is to setup the admin project to be a remote:

As you can tell from the above command we are basically using the same parameters as discussed above with the difference being appName, mfeType and port. We need to ensure each host/remote runs on a different port during local development.


The schematic creates the same files and similar changes as we discussed above with few exceptions:

  • The schematic does not create serve-mfe command for the remotes.
  • The schematic creates a new module called remote-entry in the app. In this case of admin application, the module is used as the entry module for our remote and it is used in the webpack.config.js file.


The remote-entry module is the module we expose in the our remote configuration so it can be utilized in the shell. Example configuration looks like:

We need to add the remote we just created to the shell webpack.config.js so the shell is aware of the admin module it is responsible for loading and unloading. An example configuration looks like the following:

Finally we need to add a route to our shell to open the remote we created. Similar to this code snippet:

Unfortunately, Typescript does not like admin/module since it does not exist at compile time. To solve this you can add a types.d.ts file in the root of the src directory in the shell project and add declare module admin/Module;.

The ports we defined in the commands we are executing are used for local development that allow you to run multiple Angular project simultaneously.

We will continue by setting up the dashboard project as the next remote that we use. Thus, we issue the following command:

This will create similar files as the admin project, which we discussed above. We start by adding the dashboard to the shell configuration. An example configuration looks like the following:

We need to add a route to our shell to open the dashboard we created. Similar to this code snippet:

Also, ensure you add declare module 'dashboard/Module'; to the types.d.ts file we created earlier.

Run Application

At this time we finished configuring our applications, and we are ready to try it out. To do that you would need to start all three applications. To accomplish this type the following commands into a separate terminals.

Or you can combine all three commands in the array of commands under serve-mfe in angular.json. This allows you to just use just one command nx serve-mfe instead of 3 commands.

Another option is Concurrently, which allows you to run multiple command simultaneously.


Start our host and remotes based on the ports we configured earlier by running any of the options mentioned above. If you open a browser to the host (localhost:5000) and navigate to the the admin and/or dashboard routes you will see the content of the entry.component.ts in each project.

Using Angular CLI

The implementation of Micro Frontends with Angular CLI is very similar to the way we implemented it with Nx Workspace. We will begin with creating an empty workspace with the Angular CLI and creating the three projects similar to what we did above. Then use ng add schematics to add the Micro Frontends configuration for each project.

Create an empty workspace

To begin our implementation with the Angular CLI, we begin by creating an empty workspace so we can add the projects we need for this Micro FrontEnd. The command we will issue to create an empty workspace is:

This schematic will generate few files but no project since we added --create-application false. This allows us to add multiple applications to the project.

Adding Angular Application

Create three different applications and use the same names we did in the above section. The commands we will issue are:

We now have all the applications we need to start configuring our Micro FrontEnds.

Setup the host

At this point we use the Angular ng add schematic to add the configuration we need for our host. The command we will issue is:

Unlike Nx Schematic, you can not state if you are adding the Micro FrontEnd configuration to a host or remote. After we run this command we will have 3 new files and updates to existing files. As discussed earlier these changes include:

  • main.ts
  • bootstrap.ts
  • webpack.config.js & webpack.prod.config.js. You need to add you module for both hosts and remotes. Ensure that you update the file to match your needs.
  • package.json : The schematic adds @angular-architects/module-federation package and installs it. It also adds a new npm script called run:all using the @angular-architects/module-federation server.

  • angular.json : The schematic changes the builder for build, serve, extract-i18n and test to use the ngx-build-plus. It also adds extraWebpackConfig to the above commands including the port we specified.

Setup the Remote(s)

As mentioned earlier when using the ng add schematic there are no settings to configure if you are running the schematic for a host or a remote. We will run a similar command when setting up the host and setting the project property and port. The following command adds the Micro FrontEnd configuration to admin project.

The result of this schematic is very similar to the results of setting up the host. Ensure you update the webpack.config.js to update what we exposed out of the remote. In our case we are going to expose the entire app.module.ts. Your configuration should look like:

Next, we will add Micro FrontEnd configuration to the dashboard project using the following command:

Ensure you update the webpack.config.js to update what we expose out of the remote. In our case we are going to expose the entire app.module.ts. Your configuration should look like:

Production Deployment

So far we have run everything locally and things seems to be working, but we need to put our products in front of our customers. To deploy to production or any other environment such as qa or staging start by duplicating the settings in webpack.config.js to match each environment's settings. Let's make a few assumptions on our fake production environment:

  • We are using AWS to deploy our application. As per our example we have the shell, admin, and dashboard applications.
  • Each one of these applications is deployed to their own S3 bucket. To continue our example, let's also assume each S3 bucket is named as appName-bucket, which means we have shell bucket, admin-bucket, and dashboard-bucket.
  • Finally, let's assume all of the S3 buckets have appropriate permissions to communicate with each other.


You would adjust the remote(s) addresses in the shell configuration which you will deploy to the shell-bucket such as:

You must ensure that each S3 bucket has the proper permissions to communicate with each other, which is an important perquisite. How to configure these permissions is beyond the scope of this article.

Although this setup will work and your app will deploy and run, it will be hard to maintain this with many applications and multiple environments. There are multiple ways to solve this concern. One such way is Dynamic Remote Container feature of Module Federation of Webpack. You can create also a mapping configuration to use in your Webpack based on the environment. You need to determine the best path that suites your organizational needs.

Mirco Frontends

This was a brief introduction to Micro Frontends with Angular. There are a lot more things you can do with Micro Frontends. You can switch to Dynamic Federation, you can expose components from a remote, and you can have shared libraries/functionality between all remotes. We just touched the surface on all the things you can do with Micro Frontends.

View Details
- +
Sold Out