Angular : Micro Frontend (Module Federation)
Micro Frontends in Angular refer to the architectural approach of breaking down a large monolithic Angular application into smaller, self-contained and independent frontend modules. Each module represents a specific feature or functionality of the application and can be developed, deployed, and maintained separately.
Module Federation is a powerful feature provided by Webpack that enables the implementation of Micro Frontends in Angular. It allows you to dynamically load and integrate remote Angular modules (Micro Frontends) into a main application shell.
Module Federation handles the dynamic loading and sharing of modules, including their dependencies, at runtime. It enables applications to share code and resources, reducing duplication and improving the overall performance and development experience.
Here’s a step-by-step explanation of how you can implement Micro Frontends in Angular using Module Federation:
Step 1: Set up the Main Application Shell
- Create an Angular project using the Angular CLI:
ng new main-app
. - Configure the project to use Module Federation. Install the necessary dependencies:
npm install @angular-architects/module-federation@next webpack@5 webpack-cli@4
- Create a
webpack.config.js
file at the root of the project:
// webpack.config.js
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin;
module.exports = {
output: {
uniqueName: 'mainApp',
},
plugins: [
new ModuleFederationPlugin({
name: 'mainApp',
remotes: {},
shared: ['@angular/core', '@angular/common', '@angular/router'],
}),
],
};
Step 2: Create Micro Frontend Projects
- Create individual Angular projects for each Micro Frontend. For example, create two projects:
product-listing
andshopping-cart
:
ng generate application product-listing
ng generate application shopping-carts
Step 3: Configure Module Federation in Micro Frontends
- In the
webpack.config.js
file of each Micro Frontend project, configure Module Federation:
// product-listing/webpack.config.js
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin;
module.exports = {
output: {
uniqueName: 'productListing',
publicPath: 'auto',
},
plugins: [
new ModuleFederationPlugin({
name: 'productListing',
filename: 'remoteEntry.js',
exposes: {
'./ProductListingModule': './src/app/product-listing/product-listing.module.ts',
},
shared: ['@angular/core', '@angular/common', '@angular/router'],
}),
],
};
// shopping-cart/webpack.config.js
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin;
module.exports = {
output: {
uniqueName: 'shoppingCart',
publicPath: 'auto',
},
plugins: [
new ModuleFederationPlugin({
name: 'shoppingCart',
filename: 'remoteEntry.js',
exposes: {
'./ShoppingCartModule': './src/app/shopping-cart/shopping-cart.module.ts',
},
shared: ['@angular/core', '@angular/common', '@angular/router'],
}),
],
};
Step 4: Build and Deploy Micro Frontends
- Build each Micro Frontend project individually:
ng build product-listing
ng build shopping-cart
- Deploy the built Micro Frontend projects to separate URLs, such as
http://localhost:3001
andhttp://localhost:3002
.
Step 5: Integrate Micro Frontends into the Main Application Shell
- Update the
webpack.config.js
file of the main application shell to include the remote entries of the Micro Frontends:
// webpack.config.js
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin;
module.exports = {
output: {
uniqueName: 'mainApp',
},
plugins: [
new ModuleFederationPlugin({
name: 'mainApp',
remotes: {
productListing: 'productListing@http://localhost:3001/remoteEntry.js',
shoppingCart: 'shoppingCart@http://localhost:3002/remoteEntry.js',
},
shared: ['@angular/core', '@angular/common', '@angular/router'],
}),
],
};
- Update the routing configuration in the
app.module.ts
file of the main application shell to lazy load the remote Angular modules:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, Routes } from '@angular/router';
import { loadRemoteModule } from '@angular-architects/module-federation';
const routes: Routes = [
{ path: 'product-listing', loadChildren: () => loadRemoteModule('productListing', 'ProductListingModule') },
{ path: 'shopping-cart', loadChildren: () => loadRemoteModule('shoppingCart', 'ShoppingCartModule') },
];
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot(routes),
],
declarations: [],
bootstrap: [AppComponent],
})
export class AppModule { }
Step 6: Run the Main Application Shell
- Build and run the main application shell:
ng build
ng serve
- Access the main application shell at
http://localhost:4200
and navigate to the Micro Frontends' routes (product-listing
andshopping-cart
). The remote Angular modules will be dynamically loaded and integrated into the main application shell.
By following these steps, you can implement Micro Frontends in Angular using Module Federation. Each Micro Frontend can be developed, deployed, and scaled independently, enabling a modular and decoupled architecture for your Angular application
In summary, Web Components focus on encapsulating UI components with reusable HTML, CSS, and JavaScript, while Module Federation focuses on dynamically loading and sharing modules between different applications at runtime. While they can be used together in a micro frontend architecture, they serve different purposes and address different aspects of web development.