Skip to content

Microfrontends

Microfrontends extend microservices principles to the frontend. Each micro-frontend is independently developed, tested, and deployed, aligned with a business domain.

5-Stage Migration Process

1. Preliminary Analysis

  • Assess application complexity and scale
  • Formulate migration goals
  • Evaluate team experience
  • Apply DDD to identify bounded contexts

2. Define Business Functions

Each microfrontend aligns with a domain: product catalog, checkout, user profile, admin panel. Team autonomy is the primary driver.

3. Choose Integration Method

Method Type Pros Cons
Webpack Module Federation Build/Runtime Share modules at runtime, most popular Complex config
Single-SPA Client-side Framework-agnostic orchestrator Learning curve
Server-side composition Server-side Good SEO, fast initial load Less interactive
iframes Client-side Full isolation Limited communication
Web Components Client-side Standards-based Browser support varies
Hybrid Both Best of both worlds Most complex

4. Framework/Tool Selection

Webpack Module Federation:

// Host app
new ModuleFederationPlugin({
  remotes: {
    checkout: "checkout@http://checkout.example.com/remoteEntry.js"
  },
  shared: { react: { singleton: true } }
})

// Checkout micro-frontend
new ModuleFederationPlugin({
  name: "checkout",
  exposes: { "./CheckoutForm": "./src/CheckoutForm" },
  shared: { react: { singleton: true } }
})

Single-SPA: Framework-agnostic orchestrator. Register apps, manage lifecycle (bootstrap, mount, unmount). Supports React, Vue, Angular, Svelte simultaneously. Route-based activation.

5. Inter-Module Communication

Method Coupling Use Case
API/BFF Loose Each MFE has dedicated backend
Custom Events Loose window.dispatchEvent / addEventListener
URL/routing Loose Pass state via URL parameters
Global state Tight (avoid) Shared Redux - breaks isolation

Key Architectural Decisions

Shared dependencies: Balance bundle size (share React) vs independence (each bundles own). Module Federation shared config with version ranges.

Styling isolation: CSS Modules, Shadow DOM, CSS-in-JS with unique prefixes, BEM with team prefix.

Authentication: Centralized auth service. Shell handles login, passes token to microfrontends.

Error boundaries: Each MFE has error boundary. One failure must not crash others.

When to Use

Good fit: Large teams (5+ frontend devs), multiple teams on same product, independent deployment needed, different tech requirements per section, legacy migration (Strangler Fig).

Poor fit: Small team (<5 devs), simple app, tight coupling between features, performance-critical SPA, team lacks DevOps maturity.

Performance Considerations

  • Initial load may be slower (multiple bundles)
  • Lazy loading on route activation
  • Share common dependencies (React, design system)
  • Pre-fetch critical microfrontends
  • SSR for initial page load
  • Monitor bundle sizes independently

Gotchas

  • CSS conflicts between MFEs - always use isolation strategy (CSS Modules, Shadow DOM)
  • Shared state breaks independence - prefer events/URL over global store
  • Version conflicts - different MFEs wanting different React versions. Module Federation singleton: true helps but doesn't eliminate
  • Testing integration - unit tests per MFE are easy, testing communication between MFEs requires dedicated integration test infrastructure
  • Deployment coordination still needed for shared contracts even with independent deploys

See Also