← Back to list

Need Independent Deployments in Angular? Use Module Federation — MFE

Microfrontends (MFEs) are having a moment.

Rainbow Life · 2025-11-21 10:27 · 52 claps · 5.7 min read paywalled
#mfe #angular #frontend-development #micro-front-end #angular-microfrontend
Open on Medium ↗
Wiki topics: 🌐 · Web Development

Need Independent Deployments in Angular? Use Module Federation — MFE

AI Generated Image

AI Generated Image

Microfrontends (MFEs) are having a moment.

If you work in a large enterprise Angular app, you know the feeling: the builds are slow, the bundle is enormous, teams step on each other’s toes, and every upgrade feels like a tax audit.

Somewhere between “Who touched the shared module?” and “Why did the whole app break when I changed a button style?” you start wondering if there’s a better way.

Enter Module Federation — a Webpack 5 superpower that Angular (especially version 16+) embraces beautifully.

It lets you load code at runtime from other apps. Yes, runtime. As in: “the code wasn’t here a second ago, but now it is.”

This guide walks you through Module Federation architecture in Angular the way a senior dev would explain it over a cup of coffee — diagrams, jokes, real-world patterns, Nx integration, SSR pitfalls, the whole buffet.

1. What Module Federation Actually Solves (AKA: The Pain Section)

Let’s be honest about big Angular apps.

They tend to become:

  • 💣 Massive bundles (“Why is the login page 8MB?”)
  • 🐢 Slow builds (“Go for lunch while it compiles.”)
  • 😵 Cross-team chaos (“Who refactored the shared-utils folder?!”)
  • 🥵 Tight coupling (“Feature A broke feature Z again.”)
  • 😭 Painful upgrade cycles (“Don’t touch RxJS today, we’ll deal with it next quarter.”)

Module Federation says: “Relax, we can fix that.”

It gives you:

  • Independent deployment
  • Runtime loading of remote code
  • Version-agnostic library sharing
  • True team autonomy
  • Incremental Angular upgrades

In other words:

Module Federation turns your Angular app from a monolith into a constellation of apps that come together at runtime.

Imagine your main app (the Shell) as a conductor, and each MFE is a musician playing independently but in sync.

2. High-Level Architecture (The Big Picture)

Here’s the enterprise-style visual:

INTERNET
     │
┌────┴──────────┐
│ Reverse Proxy │  (NGINX / CDN / API Gateway)
└────┬──────────┘
     │ Requests
 ┌───┼─────────────────────────────────────────────┐
 │   │                                             │
 ▼   ▼                                             ▼
┌──────────┐  ┌──────────────┐             ┌────────────┐
│  Shell   │  │   MFE A      │             │   MFE B     │
│ (Host)   │  │  (Remote)    │             │  (Remote)   │
└────┬─────┘  └──────┬───────┘             └──────┬─────┘
     │ Webpack MF Runtime                      │
     └──────────────────────────────────────────┘
     Dynamically pulls remote bundles at runtime
  • Shell = Host
  • Billing / CRM / Orders = Remotes

The Shell owns:

  • Global layout
  • Navigation
  • Theme
  • Authentication
  • Runtime remote configuration

Each Remote owns its domain (Billing, CRM, Inventory, etc.)

This separation is the secret to scaling large organizations.

3. Internal Architecture (What’s Inside the Shell & Remotes)

Let’s pop the hood.

Shell / Host

┌──────────────────────────────────────────────────────┐
│ AppComponent (header, footer, layout)                │
│     │                                                │
│     ▼                                                │
│ Shell Routing Module                                 │
│     │                                                │
│     ├─ /home        → local feature module           │
│     ├─ /profile     → local feature module           │
│     └─ /billing     → remote module (MFE)            │
└──────────────────────────────────────────────────────┘

Remote App (e.g., Billing)

┌──────────────────────────────────────────────────────┐
│  Exposed Entry Module                                 │
│        │                                              │
│        └── Remote Routing Module                      │
│              ├── /billing/home                        │
│              ├── /billing/invoices                    │
│              └── /billing/settings                    │
└──────────────────────────────────────────────────────┘

The Shell doesn’t care how the Remote arranges its internals — that’s the remote’s job.

The Shell only knows one thing: how to load its exposed entry module. Clean, decoupled, elegant.

4. Webpack Module Federation Configuration (Angular 14–20+)

Angular 14+ uses Webpack 5 under the hood, so Module Federation is now basically a first-class citizen.

Thanks to the amazing @angular-architects/module-federation, configuration becomes almost too easy.

Shell config

// shell/webpack.config.js
const { withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');

module.exports = withModuleFederationPlugin({
  remotes: {
    billing: "billing@http://localhost:4201/remoteEntry.js",
    crm:     "crm@http://localhost:4202/remoteEntry.js"
  },
  shared: {
    "@angular/core": { singleton: true, strictVersion: true },
    "@angular/common": { singleton: true },
    "@angular/router": { singleton: true },
  }
});

Remote config

// remote/webpack.config.js
module.exports = withModuleFederationPlugin({
  name: 'billing',
  exposes: {
    './Module': './src/app/billing/billing.module.ts',
  },
});

Boom. The Shell can now load Billing at runtime.

5. Deep Dive: How Module Federation Works Behind the Scenes

Let’s follow the flow:

SHELL LOADS
     │
     ▼
┌────────────┐
│remoteEntry │  ← remote's definition file
└─────┬──────┘
      │ registers exposed modules + shared libs
      ▼
┌────────────┐
│Shared Scope│  ← ensures singletons
└─────┬──────┘
      │
Shell requests "./Module"
      │
MF runtime resolves it from Billing

Magic? No. Brilliant engineering? Yes.

At runtime, the Shell becomes a conductor calling:

“Billing, I need your module!”

And Billing responds by sending over the code on the fly.

6. Routing Architecture (Where the Magic Meets Angular)

Shell routes

{
  path: 'billing',
  loadChildren: () =>
    loadRemoteModule({
      type: 'module',
      remoteName: 'billing',
      exposedModule: './Module'
    }).then(m => m.BillingModule)
}

Remote routes

const routes: Routes = [
  { path: '', component: BillingHomeComponent },
  { path: 'invoices', component: InvoiceListComponent },
  { path: 'settings', component: BillingSettingsComponent }
];

The Shell only loads the entry module. The Remote lazy-loads everything else — sweet efficiency.

7. Communication Between MFEs (AKA: “How do they talk?”)

This is where most teams struggle.

✔ Allowed + Recommended

  • Custom Browser Events
  • Shared RxJS service (through shared singleton)
  • Host-level message bus
  • URL parameters
  • Shared NgRx store (careful!)
  • APIs
  • WebSockets

✘ Avoid at all costs

  • Cross-MFE DI service mutation
  • Direct component imports
  • Using global window hacks
  • Sharing huge domain libraries

Recommended Architecture (Event Bus)

SHELL
┌──────────────────────────────┐
│  Event Hub (RxJS Subject)    │
└─────────────┬────────────────┘
              │
      ┌───────▼──────┐   ┌───────▼──────┐
      │ Billing MFE   │   │  CRM MFE      │
      └───────────────┘   └───────────────┘

Broadcast → everyone listens. Everyone publishes → Shell forwards if needed.

Decoupled. Clean. Maintainable.

8. Shared Libraries & Versioning (Where Enterprises Win or Die)

To avoid version hell:

  • Use strictVersion: true
  • Align Angular versions across MFEs
  • Use Nx to sync dependencies
  • Share only what must be singleton
  • For libs like lodash → don’t use singleton

Example:

shared: {
  '@angular/*': { singleton: true, strictVersion: true },
  'rxjs': { singleton: true },
  'lodash': { singleton: false }
}

9. Deployment Architecture (The Real Battle)

This is where Module Federation truly shines.

Your CDN / reverse proxy maps:

/shell/*             → Shell SPA
/billing/remoteEntry.js  
/crm/remoteEntry.js
/orders/remoteEntry.js

But here’s the trick:

DO NOT hardcode URLs. Use a runtime remotes.json file.

shell/assets/remotes.json

{
  "billing": "https://cdn.app.com/billing/remoteEntry.js",
  "crm":     "https://cdn.app.com/crm/remoteEntry.js"
}

This allows deployments without rebuilding the Shell.

10. Nx Integration (Highly Recommended)

Nx is basically the Tony Stark suit for Module Federation.

Benefits:

  • Distributed builds
  • Affected graph
  • Instant caching
  • Shared library workspace
  • Version alignment
  • CI/CD isolation

Architecture:

┌────────────────── Nx Workspace ──────────────────┐
   │                │                 │
   │           ┌─────────┐     ┌─────────┐
   │           │ Shell   │     │ Billing │
   │           └─────────┘     └─────────┘
   │                  │           │
   │        └── depends on Shared Libs ─────┘

Only the MFEs you’ve touched get rebuilt. Your build team will love you.

11. SSR + Module Federation (The Spicy Section)

SSR + MFEs = tricky.

Why?

  • remoteEntry.js cannot run in Node
  • Remotes must ship server bundles
  • Often remotes skip SSR entirely
  • Shell handles the initial SSR

Many teams do:

✔ SSR on Shell ✘ No SSR on Remotes

Simplifies life dramatically.

12. Advanced Architecture Patterns

12.1 Domain-Driven MFEs

Split MFEs by business domains:

  • Billing → invoices, payments, reports
  • CRM → customers, leads, interactions
  • Inventory → warehouses, items, tracking

12.2 UI Composition Patterns

A) Route-Level (most common) B) Component-Level (shell imports widgets) C) Widget Federation (dashboard cards)

12.3 Auth & Permissions

Shell handles:

  • JWT
  • RBAC
  • Navigation
  • Session

Remotes just plug in and listen.

13. Security Architecture

Module Federation involves loading remote JavaScript… which can be risky.

Best practices:

  • Strict CORS
  • HTTPS only
  • CSP headers
  • Use approved remote hosts
  • No random dynamic URLs

14. Failure Handling & Resilience

Things will break — prepare for it.

  • Retry strategy
  • Circuit breakers
  • Fallback UIs
  • Health endpoints
  • Rollback pipelines

If remote fails:

loadRemoteModule()
  .catch(() => redirectToErrorPage());

15. How MFEs Transform Team Structure

MFEs allow teams to work like microservices teams.

Before MFEs:

  • Big bang deployments
  • Shared ownership (no one actually owned it)
  • Every change risked breaking 20 features

After MFEs:

  • Each team owns a domain
  • Each MFE deploys independently
  • Faster cycles
  • Easier experiments

Everyone wins.

16. Final Architecture (Everything Comes Together)

Browser
   │
   ▼
Loads Shell SPA
   │
   ▼
Shell loads remotes dynamically
┌──────────────────────────────────────────────────────────────┐
│ SHELL                                                         │
│ - Layout, nav, auth                                           │
│ - Event bus                                                   │
│ - Remote config loader                                        │
│ - Global services                                             │
└─────────┬─────────────────────────────────────────────────────┘
          │
   ┌──────▼────────┐     ┌──────▼─────────┐
   │ Billing MFE    │     │  CRM MFE        │
   └───────────────┘     └─────────────────┘
          │                    │
   ┌──────▼───────────┐  ┌────▼────────────┐
   │ Shared libraries  │  │ Auth / API libs │
   └───────────────────┘  └────────────────┘

This setup gives you:

  • Independent deployments
  • Runtime composition
  • Runtime configuration
  • Shared layout/auth
  • Domain isolation
  • True scalability

17. Conclusion

Module Federation doesn’t just change how Angular apps are built — it changes how teams work.

It turns Angular into a modular, scalable application platform with:

✔ Better autonomy ✔ Faster releases ✔ Smaller bundles ✔ Easier upgrades ✔ Better performance ✔ Cleaner domain boundaries

When paired with:

  • Nx
  • Runtime configuration
  • Event bus architecture
  • Strict version management
  • Smart shared libraries

Module Federation becomes one of the strongest front-end architectures for enterprise-scale Angular apps.

https://youtu.be/rmEfDdBqFa8


메타데이터
post_id
d3c8aa3b6f57
slug
need-independent-deployments-in-angular-use-module-federation-mfe-d3c8aa3b6f57
url
https://medium.com/@anumathew16/need-independent-deployments-in-angular-use-module-federation-mfe-d3c8aa3b6f57
canonical_url
https://medium.com/@anumathew16/need-independent-deployments-in-angular-use-module-federation-mfe-d3c8aa3b6f57
author_url
https://medium.com/@anumathew16
status
ok
fetched_at
2026-06-23 17:05:31