The size and complexity of contemporary enterprise applications are increasing. A single monolithic frontend becomes challenging to maintain and implement when teams grow and features change on their own. By dividing huge applications into smaller, independently deployable components that are individually owned by different teams, Micro Frontends (MFEs) provide a scalable solution.

Angular now offers a natural and effective method of implementing Micro Frontends without complicated runtime integrations thanks to Webpack 5 Module Federation. This article provides a step-by-step implementation guide for integrating numerous micro frontends within a single shell application, as well as an explanation of Module Federation's benefits in Angular.

1. Understanding Micro Frontends
A Micro Frontend Architecture divides a large web application into multiple independent applications — or micro apps — that can:

  • Be developed and deployed separately
  • Use different versions of Angular or other frameworks
  • Communicate seamlessly within a unified user experience


Each micro frontend (MFE) handles a specific domain, such as:

  • orders
  • inventory
  • customers


These are then composed dynamically by a Shell (Host) application.

2. What is Module Federation?

Module Federation (introduced in Webpack 5) allows multiple applications to share code and load remote modules dynamically at runtime.

Key Concepts

  • Host – The main application that loads other micro frontends.
  • Remote – A standalone micro frontend that exposes certain modules/components.
  • Shared Libraries – Dependencies (like Angular, RxJS, or common UI libraries) that can be shared between host and remotes to prevent duplication.


3. Setting Up the Environment
Prerequisites

    Node.js (>= 18)

    Angular CLI (>= 17)

    Webpack 5 (comes by default with Angular 12+)

    @angular-architects/module-federation plugin

Step 1: Install the Module Federation Plugin

npm install @angular-architects/module-federation --save-dev

4. Creating the Applications
Step 2: Generate the Shell and Micro Frontends

ng new mfe-shell --routing --style=scss
ng new mfe-orders --routing --style=scss
ng new mfe-inventory --routing --style=scss

Each app runs independently at first.

5. Configuring Module Federation
Step 3: Configure the Host (Shell)

Navigate to the shell app and run:
ng add @angular-architects/module-federation --project mfe-shell --type host

This creates a webpack.config.js with placeholders to load remote apps.

Example configuration:
// mfe-shell/webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
const mf = require('@angular-architects/module-federation/webpack');

module.exports = {
  output: {
    uniqueName: "mfeShell",
    publicPath: "auto",
  },
  plugins: [
    new ModuleFederationPlugin({
      remotes: {
        "mfeOrders": "mfeOrders@http://localhost:4201/remoteEntry.js",
        "mfeInventory": "mfeInventory@http://localhost:4202/remoteEntry.js",
      },
      shared: mf.share({
        "@angular/core": { singleton: true, strictVersion: true },
        "@angular/common": { singleton: true, strictVersion: true },
        "@angular/router": { singleton: true, strictVersion: true },
      }),
    }),
  ],
};


Step 4: Configure a Remote Application
For the mfe-orders app:
ng add @angular-architects/module-federation --project mfe-orders --type remote --port 4201

Generated webpack.config.js example:
new ModuleFederationPlugin({
  name: "mfeOrders",
  filename: "remoteEntry.js",
  exposes: {
    "./OrdersModule": "./src/app/orders/orders.module.ts",
  },
  shared: mf.share({
    "@angular/core": { singleton: true, strictVersion: true },
    "@angular/common": { singleton: true, strictVersion: true },
    "@angular/router": { singleton: true, strictVersion: true },
  }),
}),


Do the same for mfe-inventory (on port 4202).

6. Consuming Remote Modules in the Shell

In the shell’s routing configuration:
const routes: Routes = [
  {
    path: 'orders',
    loadChildren: () =>
      loadRemoteModule({
        type: 'module',
        remoteEntry: 'http://localhost:4201/remoteEntry.js',
        exposedModule: './OrdersModule',
      }).then(m => m.OrdersModule),
  },
  {
    path: 'inventory',
    loadChildren: () =>
      loadRemoteModule({
        type: 'module',
        remoteEntry: 'http://localhost:4202/remoteEntry.js',
        exposedModule: './InventoryModule',
      }).then(m => m.InventoryModule),
  },
];

Now, navigating to /orders or /inventory in the shell dynamically loads the respective remote application.

7. Sharing Common Libraries
To reduce bundle size and maintain consistency:

  • Share Angular core libraries (@angular/core, @angular/common)
  • Share UI component libraries (like PrimeNG or Material)
  • Share custom libraries (like a design system or common services)

You can modify webpack.config.js in each project:
shared: mf.share({
  "@angular/core": { singleton: true, strictVersion: true },
  "@angular/common": { singleton: true, strictVersion: true },
  "@angular/router": { singleton: true, strictVersion: true },
  "shared-lib": { singleton: true, import: "shared-lib" },
}),


8. Running and Testing
Start all apps in separate terminals:
ng serve mfe-orders --port 4201
ng serve mfe-inventory --port 4202
ng serve mfe-shell --port 4200


Open
http://localhost:4200/orders
http://localhost:4200/inventory

You’ll notice the shell dynamically loads content from the micro frontends.

9. Deployment and Versioning

Each MFE can:

  • Have its own repository
  • Be deployed independently (e.g., on Azure Blob, AWS S3, or CDN)
  • Expose its remoteEntry.js file via public URL

The shell always loads the latest version at runtime — no redeployment required for the entire app.
10. Advantages of Using Module Federation in Angular

  • True decoupling: Teams can work independently without merge conflicts.
  • Independent deployments: Each feature or domain can be deployed separately.
  • Version flexibility: Micro frontends can use different Angular versions.
  • Performance optimization: Shared dependencies reduce duplication.
  • Scalable architecture: Perfect for enterprise-level applications.


11. Real-World Use Cases

  • ERP systems with independent modules like Finance, Inventory, and Sales.
  • Multi-tenant platforms where different clients require customized frontends.
  • Product suites where each product has its own lifecycle but unified branding.

12. Conclusion
Integrating Micro Frontends using Module Federation in Angular provides a robust foundation for building scalable, modular, and future-proof enterprise applications.

By combining independent deployability with shared runtime integration, Module Federation eliminates the pain of monolithic frontends and empowers teams to innovate faster without sacrificing consistency or maintainability.