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-dev1.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 4200Windows:
Set-Location host-banking-app
# Add module federation schematicng add @angular-architects/module-federation --type host --port 4200This 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 4201Windows:
Set-Location mfe-loan-calculator
# Add module federation as remoteng add @angular-architects/module-federation --type remote --port 42013.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 --routingloan-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 4202Windows:
Set-Location mfe-user-dashboard
# Add module federationng add @angular-architects/module-federation --type remote --port 4202webpack.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 4203Windows:
Set-Location mfe-transaction-history
# Add module federationng add @angular-architects/module-federation --type remote --port 4203Follow 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-configWindows:
Set-Location host-banking-appng generate service services/mfe-configmfe-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 Yellow6.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-detailsWindows:
# Check if remote is runningInvoke-WebRequest -Uri "http://localhost:4201/remoteEntry.js" -UseBasicParsing
# Verify webpack configurationnpm run build -- --stats-error-detailsIssue 2: Shared dependency conflicts
# Check shared dependencies versionsnpm ls @angular/corenpm ls @angular/common
# Update webpack shared config if neededIssue 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! 🎉