Welcome to the second part of our series on enhancing Angular applications using Module Federation (MF). In this guide, we'll delve into how to seamlessly incorporate MF into an existing plain Angular application.
It's important to note that, by default, Angular CLI does not facilitate the loading of custom Webpack configurations. To address this, our approach involves updating the Angular CLI builder with a specialized custom builder. This modification enables the extension of the Webpack config file, crucial for integrating advanced features like Module Federation.
While this guide focuses on utilizing the custom builder provided by the @angular-architects/module-federation
library, you have the flexibility to replace it with an alternative builder, should your expertise permit. For those interested in exploring how to implement custom Webpack configurations within Angular CLI builders, we suggest reading the following article How To Use Custom webpack Configurations with Angular CLI Builders by DigitalOcean. This resource offers valuable insights and practical steps for customizing your Angular build process beyond the standard configurations.
Run the following command in your project's root directory:
This command configures your main project for Module Federation, updates Angular CLI configurations, creates a manifest file for loading remote entries, and reorganizes the bootstrap process.
Some Angular schematics like @angular/pwa
and @angular/material
expect bootstrapping in main.ts
. If you plan to use these, toggle the bootstrapping process temporarily:
After implementing the schematic changes, it's essential to modify the manifest file (mf.manifest.json
) and the application routing configuration (app-routing.module.ts
) to ensure proper functioning of your Angular application.
The default configuration in mf.manifest.json
is set to serve a file on port 4200
. However, this port is typically used for the main application.
To avoid conflicts, update the port for serving the secondary application. For example, change the port to 4201. Your mf.manifest.json
should reflect this change as follows:
By updating these configurations, you establish a clear and functional structure for running your main and secondary Angular applications on distinct ports, facilitating their independent operation and integration.
Simplified Example: In this guide, the manifest configuration is statically defined in a JSON file for simplicity.
Dynamic Configuration in Production: For real-life applications, it's recommended to serve the manifest configuration dynamically. This can be achieved by either:
When opting for dynamic serving, update the main.ts file to modify the URL used by the initFederation function to retrieve the manifest data. Be aware that in this configuration, if there's no internet connection, the application will fail to load. However, with a static configuration, you can handle connection errors, particularly if your app has been previously cached.
Integrating the Manifest in Routing:
Modify the Manifest File:
Update the Application Routing (app-routing.module.ts)
:
import('@@login')
).loadRemoteModule
function (imported from the @angular-architects/module-federation module
).loadRemoteModule
function with the following object:type
: Denotes the remote configuration type ('manifest'
in this case).remoteName
: The module's name as declared in the manifest.exposedModule
: Path of the module in the secondary app.The final result should look similar to the following example:
Having followed these steps, the main application is now configured to load other applications remotely. The next phase involves setting up the secondary applications to ensure they can be loaded in this manner.
Upon configuring the secondary applications, similar to the main app, several project components will be updated. Notably, this process does not create a manifest file, but it does modify the webpack.config.js
file, adding more details than what is typically found in the main application's configuration.
Instead of using --type dynamic-host
, we are going to use --type remote
instead.
webpack.config.js
file plays a crucial role. It contains an object configuration where each key-value pair resembles a route. This property dictates the modules to be exposed to the loader.Identifying Configuration Mismatch: In the current setup, the route configuration attempts to load a module named './Module', but this isn't specified in the existing Webpack configuration.
To rectify this, modify the webpack.config.js
file:
With this update, the secondary applications are correctly configured to expose the necessary modules, aligning with the remote loading requirements set in the main application.
ng serve
ng serve login
localhost:4201
in your browser, you can observe the login application operating as a standalone entity.While we currently use shareAll
from the @angular-architects/module-federation/webpack
package, a more refined approach involves sharing only necessary dependencies using the share
function. This selective sharing optimizes the application's performance and resource utilization.