This guide explains how to integrate Module Federation with Angular CLI. The @angular-architects/module-federation plugin is used to assist with this integration.
@angular-architects/module-federation plugin.To start, configure the Angular CLI to use Module Federation during the build phase. A custom builder is needed to unlock Module Federation's potential.
The @angular-architects/module-federation package provides this custom builder.
Use the ng add command to incorporate it into your projects:
The --type argument, introduced in version 14.3, ensures that only the necessary configuration is generated.
The Shell (Host) is crucial for Module Federation integration.
This section configures the Shell to support lazy-loading of a FlightModule through routing.
Start by defining the application routes, specifying a lazy-loaded FlightModule using a virtual path:
In this configuration, the path 'mfe1/Module' is a virtual representation, indicating it doesn't physically exist within the Shell application. Instead, it's a reference to a module in a separate project.
Create a type definition for the virtual path:
This helps the TypeScript compiler understand the virtual path.
Instruct Webpack to resolve all paths prefixed with mfe1 to a remote project. This is done in the webpack.config.js file:
In the remotes section, the path mfe1 is mapped to the remote micro-frontend's entry point. This entry point, generated by Webpack, contains essential information for interacting with the micro-frontend.
For development, hardcoding the remote entry's URL is enough. However, a dynamic approach is necessary for production. The concept of dynamic remotes is further explored in a dedicated documentation page on Dynamic Remotes.
shared property specifies the npm packages to be shared between the Shell and the micro-frontend(s). Using the shareAll helper method, all dependencies listed in your package.json are shared. While this facilitates a quick setup, it may lead to an excessive number of shared dependencies, which could be a concern for optimization.singleton: true and strictVersion: true settings instructs Webpack to throw a runtime error if there is a version mismatch between the Shell and the micro-frontend(s). Changing strictVersion to false would instead result in a runtime warning.requiredVersion: 'auto' option, provided by the @angular-architects/module-federation plugin, automatically determines the version from your package.json, helping to prevent version-related issues.The Micro-frontend, also known as the Remote in Module Federation, has a structure similar to a standard Angular app. It has specific routes in the AppModule and a FlightsModule for flight-related tasks. This section explains how to smoothly load the FlightsModule into the Shell (Host).
Establish the basic routes within the AppModule:
This simple routing setup navigates to a HomeComponent when the application is accessed.
Create a FlightsModule to handle flight-related operations:
This module contains a route to a FlightsSearchComponent defined as follows:
To enable the loading of FlightsModule into the Shell, expose it through the Remote's Webpack configuration:
In this configuration:
name property identifies the micro-frontend as mfe1.exposes property signifies the exposure of FlightsModule under the public name Module, allowing its consumption by the Shell.shared property lists the libraries to be shared with the Shell, using the shareAll method to share all dependencies found in your package.json. The singleton: true and strictVersion: true properties ensure that a single version of shared libraries is used, and a runtime error is triggered in case of version incompatibility, respectively.Having set up the Shell (Host) and Micro-frontend (Remote), it's time to test the configuration to ensure the seamless integration of Module Federation.
To start the Shell and Micro-frontend, use the following commands:
Navigate to the Flights section in the Shell to see the Micro-frontend being dynamically loaded.
The plugin installs an npm script run:all during the ng-add and init schematics, allowing for simultaneous serving of all applications:
The initial setup with shareAll is simple and functional, but it can result in the creation of unnecessarily large shared bundles.
To manage shared dependencies more effectively, consider switching from shareAll to using the share helper. This provides finer control over which dependencies are shared:
In this configuration, the share helper allows for explicit sharing of selected packages, enabling a more optimized bundle sharing and potentially reducing load times.