11/15/2021 12:00 AM
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:
These are awesome benefits for large development teams that work on an Enterprise size application. Micro Frontends also has some limitations:
In this article we are going to focus on setting up an Angular Micro Frontends project using the following tools:
Before we begin our implementation let's define some concepts about Micro Frontends:
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.
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.
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.
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:
After we run this command we will have 3 new files and updates to existing files. These changes include:
At this point our shell setup is complete and ready to accept remotes.
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 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.
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.
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.
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.
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.
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:
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:
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:
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.
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.