Angular MFE Module Federation Setup | Complete Configuration Guide
This guide walks you through configuring Webpack Module Federation for your Angular Micro Frontend applications, enabling them to share code and components at runtime.
🎯 Module Federation Overview
Section titled “🎯 Module Federation Overview”Module Federation is a Webpack 5 feature that allows multiple separate builds to form a single application. It enables:
- Runtime Code Sharing: Load modules from other applications at runtime
- Independent Deployment: Each MFE can be deployed separately
- Shared Dependencies: Avoid duplicating common libraries
- Dynamic Imports: Load remote modules on-demand
Key Concepts
Section titled “Key Concepts”- Host: Application that consumes remote modules (your main shell app)
- Remote: Application that exposes modules to be consumed
- Federated Modules: Components/modules shared between applications
- Shared Dependencies: Libraries shared to prevent duplication
🛠️ Step 1: Install Module Federation Dependencies
Section titled “🛠️ Step 1: Install Module Federation Dependencies”1.1 Install Angular Architects Module Federation
Section titled “1.1 Install Angular Architects Module Federation”For each application (host and all remotes), install the required packages:
Unix/macOS/Windows:
# Navigate to each project and run:npm install @angular-architects/module-federation --save-dev
# Alternative: Install specific versionnpm install @angular-architects/module-federation@^17.0.0 --save-dev
1.2 Install Supporting Dependencies
Section titled “1.2 Install Supporting Dependencies”Unix/macOS/Windows:
# Additional webpack dependenciesnpm install @angular-builders/custom-webpack --save-devnpm install webpack --save-devnpm install webpack-cli --save-dev
🚀 Step 2: Configure Host Application
Section titled “🚀 Step 2: Configure Host Application”Let’s start by configuring the host application (host-banking-app
):
2.1 Add Module Federation to Host
Section titled “2.1 Add Module Federation to Host”Unix/macOS:
cd host-banking-app
# Add module federation schematicng add @angular-architects/module-federation --type host --port 4200
Windows:
Set-Location host-banking-app
# Add module federation schematicng add @angular-architects/module-federation --type host --port 4200
This command will:
- Install necessary dependencies
- Create
webpack.config.js
- Update
angular.json
- Modify project configuration
2.2 Configure Host Webpack Config
Section titled “2.2 Configure Host Webpack Config”The generated webpack.config.js
should look like this:
const ModuleFederationPlugin = require("@module-federation/webpack");
module.exports = { mode: "development", plugins: [ new ModuleFederationPlugin({ name: "host", filename: "remoteEntry.js",
remotes: { "mfeLoanCalculator": "http://localhost:4201/remoteEntry.js", "mfeUserDashboard": "http://localhost:4202/remoteEntry.js", "mfeTransactionHistory": "http://localhost:4203/remoteEntry.js", },
shared: { "@angular/core": { singleton: true, strictVersion: true, requiredVersion: "auto" }, "@angular/common": { singleton: true, strictVersion: true, requiredVersion: "auto" }, "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: "auto" }, "@angular/router": { singleton: true, strictVersion: true, requiredVersion: "auto" }, }, }), ],};
2.3 Update Angular.json for Host
Section titled “2.3 Update Angular.json for Host”The angular.json
should be updated to use custom webpack:
{ "projects": { "host-banking-app": { "architect": { "build": { "builder": "@angular-builders/custom-webpack:browser", "options": { "customWebpackConfig": { "path": "./webpack.config.js" } } }, "serve": { "builder": "@angular-builders/custom-webpack:dev-server", "configurations": { "production": { "buildTarget": "host-banking-app:build:production" }, "development": { "buildTarget": "host-banking-app:build:development", "port": 4200 } } } } } }}
2.4 Create MFE Manifest (Dynamic Configuration)
Section titled “2.4 Create MFE Manifest (Dynamic Configuration)”Create src/assets/mf.manifest.json
for dynamic remote configuration:
{ "mfeLoanCalculator": "http://localhost:4201/remoteEntry.js", "mfeUserDashboard": "http://localhost:4202/remoteEntry.js", "mfeTransactionHistory": "http://localhost:4203/remoteEntry.js"}
🎯 Step 3: Configure Remote Applications
Section titled “🎯 Step 3: Configure Remote Applications”Now let’s configure each remote MFE:
3.1 Configure Loan Calculator MFE
Section titled “3.1 Configure Loan Calculator MFE”Unix/macOS:
cd mfe-loan-calculator
# Add module federation as remoteng add @angular-architects/module-federation --type remote --port 4201
Windows:
Set-Location mfe-loan-calculator
# Add module federation as remoteng add @angular-architects/module-federation --type remote --port 4201
3.2 Configure Loan Calculator Webpack
Section titled “3.2 Configure Loan Calculator Webpack”Update webpack.config.js
in mfe-loan-calculator
:
const ModuleFederationPlugin = require("@module-federation/webpack");
module.exports = { mode: "development", plugins: [ new ModuleFederationPlugin({ name: "mfeLoanCalculator", filename: "remoteEntry.js",
exposes: { "./LoanCalculatorModule": "./src/app/loan-calculator/loan-calculator.module.ts", "./LoanCalculatorComponent": "./src/app/loan-calculator/loan-calculator.component.ts", },
shared: { "@angular/core": { singleton: true, strictVersion: true, requiredVersion: "auto" }, "@angular/common": { singleton: true, strictVersion: true, requiredVersion: "auto" }, "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: "auto" }, "@angular/router": { singleton: true, strictVersion: true, requiredVersion: "auto" }, }, }), ],};
3.3 Create Loan Calculator Module
Section titled “3.3 Create Loan Calculator Module”Create a dedicated module for the loan calculator:
Unix/macOS/Windows:
ng generate module loan-calculator --routing
loan-calculator.module.ts:
import { NgModule } from '@angular/core';import { CommonModule } from '@angular/common';import { FormsModule } from '@angular/forms';import { RouterModule } from '@angular/router';
import { LoanCalculatorRoutingModule } from './loan-calculator-routing.module';import { LoanCalculatorComponent } from './loan-calculator.component';
@NgModule({ declarations: [ LoanCalculatorComponent ], imports: [ CommonModule, FormsModule, LoanCalculatorRoutingModule ], exports: [ LoanCalculatorComponent ]})export class LoanCalculatorModule { }
loan-calculator-routing.module.ts:
import { NgModule } from '@angular/core';import { RouterModule, Routes } from '@angular/router';import { LoanCalculatorComponent } from './loan-calculator.component';
const routes: Routes = [ { path: '', component: LoanCalculatorComponent }];
@NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule]})export class LoanCalculatorRoutingModule { }
3.4 Configure User Dashboard MFE
Section titled “3.4 Configure User Dashboard MFE”Unix/macOS:
cd mfe-user-dashboard
# Add module federationng add @angular-architects/module-federation --type remote --port 4202
Windows:
Set-Location mfe-user-dashboard
# Add module federationng add @angular-architects/module-federation --type remote --port 4202
webpack.config.js for user dashboard:
const ModuleFederationPlugin = require("@module-federation/webpack");
module.exports = { mode: "development", plugins: [ new ModuleFederationPlugin({ name: "mfeUserDashboard", filename: "remoteEntry.js",
exposes: { "./UserDashboardModule": "./src/app/user-dashboard/user-dashboard.module.ts", "./UserDashboardComponent": "./src/app/user-dashboard/user-dashboard.component.ts", },
shared: { "@angular/core": { singleton: true, strictVersion: true, requiredVersion: "auto" }, "@angular/common": { singleton: true, strictVersion: true, requiredVersion: "auto" }, "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: "auto" }, "@angular/router": { singleton: true, strictVersion: true, requiredVersion: "auto" }, }, }), ],};
Create corresponding module files similar to the loan calculator.
3.5 Configure Transaction History MFE
Section titled “3.5 Configure Transaction History MFE”Unix/macOS:
cd mfe-transaction-history
# Add module federationng add @angular-architects/module-federation --type remote --port 4203
Windows:
Set-Location mfe-transaction-history
# Add module federationng add @angular-architects/module-federation --type remote --port 4203
Follow the same pattern for webpack configuration and module creation.
🔗 Step 4: Configure Host to Load Remotes
Section titled “🔗 Step 4: Configure Host to Load Remotes”4.1 Update Host App Routing
Section titled “4.1 Update Host App Routing”Update app-routing.module.ts
in the host application:
import { NgModule } from '@angular/core';import { RouterModule, Routes } from '@angular/router';import { loadRemoteModule } from '@angular-architects/module-federation';
const routes: Routes = [ { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, { path: 'dashboard', loadChildren: () => loadRemoteModule({ type: 'module', remoteEntry: 'http://localhost:4202/remoteEntry.js', exposedModule: './UserDashboardModule' }).then(m => m.UserDashboardModule) }, { path: 'loan-calculator', loadChildren: () => loadRemoteModule({ type: 'module', remoteEntry: 'http://localhost:4201/remoteEntry.js', exposedModule: './LoanCalculatorModule' }).then(m => m.LoanCalculatorModule) }, { path: 'transactions', loadChildren: () => loadRemoteModule({ type: 'module', remoteEntry: 'http://localhost:4203/remoteEntry.js', exposedModule: './TransactionHistoryModule' }).then(m => m.TransactionHistoryModule) }];
@NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule]})export class AppRoutingModule { }
4.2 Create Navigation in Host App
Section titled “4.2 Create Navigation in Host App”Update app.component.html
in the host application:
<div class="app-container"> <header class="app-header"> <nav class="navbar"> <div class="nav-brand"> <h1>🏦 Banking Platform</h1> </div> <ul class="nav-links"> <li><a routerLink="/dashboard" routerLinkActive="active">Dashboard</a></li> <li><a routerLink="/loan-calculator" routerLinkActive="active">Loan Calculator</a></li> <li><a routerLink="/transactions" routerLinkActive="active">Transactions</a></li> </ul> </nav> </header>
<main class="app-content"> <router-outlet></router-outlet> </main>
<footer class="app-footer"> <p>© 2024 Banking Platform - Powered by Micro Frontends</p> </footer></div>
app.component.scss:
.app-container { min-height: 100vh; display: flex; flex-direction: column;}
.app-header { background: #2c3e50; color: white; padding: 0;
.navbar { display: flex; justify-content: space-between; align-items: center; padding: 1rem 2rem; max-width: 1200px; margin: 0 auto;
.nav-brand h1 { margin: 0; font-size: 1.5rem; }
.nav-links { display: flex; list-style: none; margin: 0; padding: 0; gap: 2rem;
li a { color: white; text-decoration: none; padding: 0.5rem 1rem; border-radius: 4px; transition: background-color 0.3s;
&:hover, &.active { background-color: #34495e; } } } }}
.app-content { flex: 1; padding: 2rem; max-width: 1200px; margin: 0 auto; width: 100%; box-sizing: border-box;}
.app-footer { background: #34495e; color: white; text-align: center; padding: 1rem; margin-top: auto;}
@media (max-width: 768px) { .navbar { flex-direction: column; gap: 1rem;
.nav-links { gap: 1rem; } }
.app-content { padding: 1rem; }}
🔧 Step 5: Dynamic Configuration Service
Section titled “🔧 Step 5: Dynamic Configuration Service”5.1 Create MFE Configuration Service
Section titled “5.1 Create MFE Configuration Service”Create a service to dynamically load MFE configurations:
Unix/macOS:
cd host-banking-appng generate service services/mfe-config
Windows:
Set-Location host-banking-appng generate service services/mfe-config
mfe-config.service.ts:
import { Injectable } from '@angular/core';import { HttpClient } from '@angular/common/http';import { Observable } from 'rxjs';
export interface MfeConfig { [key: string]: string;}
@Injectable({ providedIn: 'root'})export class MfeConfigService {
constructor(private http: HttpClient) { }
loadMfeConfig(): Observable<MfeConfig> { return this.http.get<MfeConfig>('/assets/mf.manifest.json'); }
async loadRemoteModule(remoteName: string, exposedModule: string) { const config = await this.loadMfeConfig().toPromise(); const remoteEntry = config![remoteName];
if (!remoteEntry) { throw new Error(`Remote ${remoteName} not found in configuration`); }
return import(/* webpackIgnore: true */ remoteEntry).then(() => { return (window as any)[remoteName]; }); }}
5.2 Create Dynamic Route Loading
Section titled “5.2 Create Dynamic Route Loading”Create a utility for dynamic route loading:
import { loadRemoteModule } from '@angular-architects/module-federation';
export interface RemoteModuleConfig { remoteEntry: string; exposedModule: string; moduleName: string;}
export function loadDynamicRemoteModule(config: RemoteModuleConfig) { return () => loadRemoteModule({ type: 'module', remoteEntry: config.remoteEntry, exposedModule: config.exposedModule }).then(m => m[config.moduleName]);}
🧪 Step 6: Testing Module Federation Setup
Section titled “🧪 Step 6: Testing Module Federation Setup”6.1 Start All Applications
Section titled “6.1 Start All Applications”Create comprehensive test scripts for your platform:
Unix/macOS (test-mfe.sh):
#!/bin/bash
echo "🚀 Starting all MFE applications for testing..."
# Function to start an application in backgroundstart_app() { local app_name=$1 local port=$2
echo "Starting $app_name on port $port..." cd $app_name npm start > ../logs/$app_name.log 2>&1 & local pid=$! echo $pid > ../logs/$app_name.pid cd .. echo "$app_name started with PID $pid"}
# Create logs directorymkdir -p logs
# Start all applicationsstart_app "mfe-loan-calculator" 4201start_app "mfe-user-dashboard" 4202start_app "mfe-transaction-history" 4203start_app "host-banking-app" 4200
echo ""echo "🎉 All applications started!"echo ""echo "📱 Application URLs:"echo " Host App: http://localhost:4200"echo " Loan Calculator: http://localhost:4201"echo " User Dashboard: http://localhost:4202"echo " Transaction History: http://localhost:4203"echo ""echo "⏳ Waiting for applications to start..."sleep 10
echo "🧪 Testing remoteEntry.js files..."curl -s -o /dev/null -w "%{http_code}" http://localhost:4201/remoteEntry.jscurl -s -o /dev/null -w "%{http_code}" http://localhost:4202/remoteEntry.jscurl -s -o /dev/null -w "%{http_code}" http://localhost:4203/remoteEntry.js
echo ""echo "✅ Module Federation setup test complete!"echo "Press any key to stop all applications..."read -n 1
# Stop all applicationsfor pidfile in logs/*.pid; do if [ -f "$pidfile" ]; then pid=$(cat "$pidfile") kill $pid 2>/dev/null rm "$pidfile" fidone
echo "🛑 All applications stopped."
Windows (test-mfe.ps1):
Write-Host "🚀 Starting all MFE applications for testing..." -ForegroundColor Green
# Function to start an application in backgroundfunction Start-App { param( [string]$AppName, [int]$Port )
Write-Host "Starting $AppName on port $Port..." -ForegroundColor Yellow Set-Location $AppName $process = Start-Process npm -ArgumentList "start" -PassThru -WindowStyle Hidden -RedirectStandardOutput "..\logs\$AppName.log" -RedirectStandardError "..\logs\$AppName.log" $process.Id | Out-File -FilePath "..\logs\$AppName.pid" Set-Location .. Write-Host "$AppName started with PID $($process.Id)" -ForegroundColor Green return $process}
# Create logs directoryNew-Item -Path "logs" -ItemType Directory -Force | Out-Null
# Start all applications$loanCalcProcess = Start-App "mfe-loan-calculator" 4201$dashboardProcess = Start-App "mfe-user-dashboard" 4202$transactionProcess = Start-App "mfe-transaction-history" 4203$hostProcess = Start-App "host-banking-app" 4200
Write-Host ""Write-Host "🎉 All applications started!" -ForegroundColor GreenWrite-Host ""Write-Host "📱 Application URLs:" -ForegroundColor CyanWrite-Host " Host App: http://localhost:4200"Write-Host " Loan Calculator: http://localhost:4201"Write-Host " User Dashboard: http://localhost:4202"Write-Host " Transaction History: http://localhost:4203"Write-Host ""Write-Host "⏳ Waiting for applications to start..." -ForegroundColor YellowStart-Sleep -Seconds 10
Write-Host "🧪 Testing remoteEntry.js files..." -ForegroundColor Bluetry { $response1 = Invoke-WebRequest -Uri "http://localhost:4201/remoteEntry.js" -UseBasicParsing; Write-Host "Loan Calculator: $($response1.StatusCode)" } catch { Write-Host "Loan Calculator: Error" }try { $response2 = Invoke-WebRequest -Uri "http://localhost:4202/remoteEntry.js" -UseBasicParsing; Write-Host "User Dashboard: $($response2.StatusCode)" } catch { Write-Host "User Dashboard: Error" }try { $response3 = Invoke-WebRequest -Uri "http://localhost:4203/remoteEntry.js" -UseBasicParsing; Write-Host "Transaction History: $($response3.StatusCode)" } catch { Write-Host "Transaction History: Error" }
Write-Host ""Write-Host "✅ Module Federation setup test complete!" -ForegroundColor GreenRead-Host "Press Enter to stop all applications"
# Stop all applicationsStop-Process -Id $loanCalcProcess.Id -Force -ErrorAction SilentlyContinueStop-Process -Id $dashboardProcess.Id -Force -ErrorAction SilentlyContinueStop-Process -Id $transactionProcess.Id -Force -ErrorAction SilentlyContinueStop-Process -Id $hostProcess.Id -Force -ErrorAction SilentlyContinue
Write-Host "🛑 All applications stopped." -ForegroundColor Yellow
6.2 Manual Testing Steps
Section titled “6.2 Manual Testing Steps”-
Start Applications:
Unix/macOS:
Terminal window chmod +x test-mfe.sh./test-mfe.shWindows:
Terminal window # Enable script execution if neededSet-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser# Run the test script.\test-mfe.ps1 -
Verify Remote Entries:
-
Test Host Application:
- Navigate to http://localhost:4200
- Click on each navigation link
- Verify MFEs load correctly
6.3 Debug Common Issues
Section titled “6.3 Debug Common Issues”Issue 1: RemoteEntry.js not found
Unix/macOS:
# Check if remote is runningcurl http://localhost:4201/remoteEntry.js
# Verify webpack configurationnpm run build -- --stats-error-details
Windows:
# Check if remote is runningInvoke-WebRequest -Uri "http://localhost:4201/remoteEntry.js" -UseBasicParsing
# Verify webpack configurationnpm run build -- --stats-error-details
Issue 2: Shared dependency conflicts
# Check shared dependencies versionsnpm ls @angular/corenpm ls @angular/common
# Update webpack shared config if needed
Issue 3: CORS issues in development
# Add to angular.json serve options:"serve": { "builder": "@angular-builders/custom-webpack:dev-server", "options": { "headers": { "Access-Control-Allow-Origin": "*" } }}
📊 Step 7: Production Configuration
Section titled “📊 Step 7: Production Configuration”7.1 Production Webpack Config
Section titled “7.1 Production Webpack Config”Create webpack.prod.config.js
for production builds:
const ModuleFederationPlugin = require("@module-federation/webpack");
module.exports = { mode: "production", plugins: [ new ModuleFederationPlugin({ name: "host", filename: "remoteEntry.js",
remotes: { "mfeLoanCalculator": "https://loan-calculator.yourdomain.com/remoteEntry.js", "mfeUserDashboard": "https://user-dashboard.yourdomain.com/remoteEntry.js", "mfeTransactionHistory": "https://transaction-history.yourdomain.com/remoteEntry.js", },
shared: { "@angular/core": { singleton: true, strictVersion: true, requiredVersion: "auto" }, "@angular/common": { singleton: true, strictVersion: true, requiredVersion: "auto" }, "@angular/router": { singleton: true, strictVersion: true, requiredVersion: "auto" }, }, }), ],};
7.2 Environment-Based Configuration
Section titled “7.2 Environment-Based Configuration”Update mf.manifest.json
structure:
{ "development": { "mfeLoanCalculator": "http://localhost:4201/remoteEntry.js", "mfeUserDashboard": "http://localhost:4202/remoteEntry.js", "mfeTransactionHistory": "http://localhost:4203/remoteEntry.js" }, "production": { "mfeLoanCalculator": "https://loan-calculator.yourdomain.com/remoteEntry.js", "mfeUserDashboard": "https://user-dashboard.yourdomain.com/remoteEntry.js", "mfeTransactionHistory": "https://transaction-history.yourdomain.com/remoteEntry.js" }}
✅ Module Federation Setup Verification
Section titled “✅ Module Federation Setup Verification”Checklist
Section titled “Checklist”- Module Federation installed in all applications
- Webpack configs created for host and remotes
- Remote modules properly exposed
- Host application configured to consume remotes
- Navigation working between MFEs
- Shared dependencies configured correctly
- RemoteEntry.js files accessible
- Dynamic routing implemented
- Production configuration prepared
- Testing script working
Expected File Structure
Section titled “Expected File Structure”Project Structure After Module Federation Setup:├── host-banking-app/│ ├── webpack.config.js│ ├── webpack.prod.config.js│ ├── src/assets/mf.manifest.json│ └── updated angular.json├── mfe-loan-calculator/│ ├── webpack.config.js│ ├── loan-calculator.module.ts│ └── updated angular.json├── mfe-user-dashboard/│ ├── webpack.config.js│ ├── user-dashboard.module.ts│ └── updated angular.json└── mfe-transaction-history/ ├── webpack.config.js ├── transaction-history.module.ts └── updated angular.json
🚀 What’s Next?
Section titled “🚀 What’s Next?”Your Module Federation setup is complete! Next steps:
- ✅ Module Federation Setup Complete
- ➡️ Continue to: Host App Configuration - Enhance the host application
- 📚 Alternative: Remote Configuration - Advanced remote setup
Your Angular MFEs can now communicate and share code at runtime! 🎉