Micro-Frontend Architecture: Webpack Module Federation, Custom Elements, and Runtime Isolation
Deconstructing independent deployment, Module Federation runtime containers, Shadow DOM encapsulation, and event buses
Part 15 in Series — Catch up on the previous article: Design System Architecture: Tokens, Components, and Themes (Part 14) before diving into this post.
At an enterprise e-commerce organization, 140 developers worked inside a single monolithic Single Page Application (SPA). During a major product launch, a junior developer on the recommendations team merged a small bug that threw an uncaught error during component initialization.
Because the entire application was built as a single monolithic bundle, the error broke the top-level React render tree. The entire site crashed—preventing millions of shoppers from browsing products or completing checkouts for 40 minutes.
Beyond blast-radius concerns, the monolithic codebase created severe delivery bottlenecks: CI builds took 55 minutes, team deployments were coupled to a single weekly release train, and merge conflicts were constant.
Micro-Frontends solve this by extending the microservices paradigm to client-side applications—decomposing a web application into semi-autonomous applications owned and deployed independently by cross-functional feature teams.
1. Architectural Topologies: Monolith vs Micro-Frontends
Monolithic Single Page Application:
[ Checkout Team ] --+
[ Search Team ] --+---> [ Single Git Repo ] ---> [ 55-Min CI Monolithic Build ] ---> [ Single Deployment ]
[ Profile Team ] --+
Micro-Frontend Architecture:
[ Search App (Team A) ] ---> [ Independent CI Pipeline ] ---> [ Deploy App A (S3/CDN) ] --+
[ Checkout App (Team B) ] ---> [ Independent CI Pipeline ] ---> [ Deploy App B (S3/CDN) ] --+-> [ Dynamic Shell ]
[ Profile App (Team C) ] ---> [ Independent CI Pipeline ] ---> [ Deploy App C (S3/CDN) ] --+
Micro-Frontend Integration Strategies
- Build-Time Integration: Shared packages imported via npm. Flaw: Requires rebuilding and re-deploying the entire shell application whenever a sub-package updates.
- Server-Side Edge Integration: Micro-frontends assembled at the CDN/Edge layer using Edge Side Includes (ESI) or SSR streaming.
- Client-Side Runtime Integration: Micro-frontends loaded dynamically at runtime via Webpack Module Federation or Web Components.
2. Webpack Module Federation Mechanics
Module Federation enables a JavaScript application to execute code loaded dynamically from a completely separate build and deployment origin at runtime, while sharing singleton dependencies (like React or Redux).
[ Host Shell Container ]
|
| 1. Dynamic Script Import ('https://checkout.enterprise.com/remoteEntry.js')
v
[ Remote Entry Manifest ]
|
| 2. Negotiate Shared Dependencies (React v18 Singleton)
v
[ Mount Remote Checkout Component in Host DOM ]
Webpack Module Federation Configuration
// Host Application (webpack.config.js)
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: "host_shell",
remotes: {
// Points to dynamically deployed remote entry point
checkout_app: "checkout_app@https://checkout.enterprise.com/remoteEntry.js"
},
shared: {
react: { singleton: true, requiredVersion: "^18.2.0" },
"react-dom": { singleton: true, requiredVersion: "^18.2.0" }
}
})
]
};
3. Runtime Isolation: Web Components & Shadow DOM
Module Federation shares JavaScript runtimes, but does not isolate CSS styles or DOM trees. A global CSS rule in a remote micro-frontend can break styles in the host shell.
Web Components provide true browser-native runtime encapsulation via the Shadow DOM:
// Encapsulated Micro-Frontend Web Component
class MicroCartWidget extends HTMLElement {
constructor() {
super();
// Attach isolated Shadow DOM Tree
const shadow = this.attachShadow({ mode: "closed" });
shadow.innerHTML = `
<style>
/* Styles inside Shadow DOM NEVER leak out to host shell! */
.cart-box { background: #111; color: #fff; padding: 12px; }
</style>
<div class="cart-box">
<h3>Shopping Cart</h3>
<button id="checkout-btn">Proceed to Checkout</button>
</div>
`;
}
}
customElements.define("micro-cart-widget", MicroCartWidget);
4. Cross-Micro-Frontend Communication: Decoupled Event Bus
Micro-frontends should never invoke internal methods on sibling micro-frontends directly. Cross-app communication must execute asynchronously via a decoupled Event Bus pattern built on top of standard browser CustomEvent dispatchers.
// Production Micro-Frontend Event Bus Architecture
export class MicroFrontendEventBus {
public static publish<T>(eventName: string, detail: T) {
const event = new CustomEvent(eventName, {
detail,
bubbles: true,
composed: true // Allows CustomEvent to cross Shadow DOM boundaries!
});
window.dispatchEvent(event);
}
public static subscribe<T>(eventName: string, handler: (detail: T) => void): () => void {
const listener = (event: Event) => {
const customEvent = event as CustomEvent<T>;
handler(customEvent.detail);
};
window.addEventListener(eventName, listener);
return () => window.removeEventListener(eventName, listener);
}
}
// Example Usage across independent teams:
// Team A (Product App) publishes event:
MicroFrontendEventBus.publish("cart:item-added", { id: "p-100", price: 29.99 });
// Team B (Cart App) listens for event:
MicroFrontendEventBus.subscribe("cart:item-added", (data) => {
console.log("Cart Updated:", data.id);
});
Summary & Key Takeaways
- Micro-Frontend Architecture: Decouples enterprise applications into independently deployable units owned by autonomous product teams.
- Module Federation: Loads remote code dynamically over HTTP at runtime while safely sharing singleton framework libraries (
react,react-dom). - Shadow DOM Isolation: Use Web Components and Shadow DOM (
attachShadow()) to achieve strict CSS style and DOM encapsulation. - Decoupled Communication: Use a browser-native
CustomEventEvent Bus withcomposed: trueto pass messages across micro-frontend boundaries without tight coupling.
References & Further Reading
- Webpack Documentation. Module Federation Architecture & Guide. Webpack.
- Geers, M. (2020). Micro-Frontends in Action. Manning Publications.
- W3C Recommendation. Shadow DOM v1 Specification. W3C Standard.
Part 16: Edge Rendering & Server Components: SSR Hydration, Static Regeneration (ISR), and React Server Components
Continue to Part 16 →