Skip to content
fearchitect
Architecture & Composition

Microfrontends & Module Federation

Independently deployable frontends composed at runtime in the browser.

By Abas TurabliReviewed

Summary

Microfrontends split a single frontend into separately owned, separately deployed slices. Webpack and Rspack Module Federation wire them together at runtime: one host app loads remote chunks on demand, sharing singletons like React across the boundary. The tradeoff is team autonomy against a new class of runtime dependency failures.

Jump to the interview angle

Microfrontend

A microfrontend is a vertical slice of UI owned by one team — its own repo, build, and deploy pipeline. The browser assembles the page from multiple independently deployed artifacts.

Module Federation (Webpack 5 / Rspack) is the dominant runtime integration mechanism. A remote exposes modules via exposes in its ModuleFederationPlugin config; a host declares those remotes in remotes and imports them as local. The host fetches the remote's manifest at runtime, then loads only the needed chunks.

Build-time vs runtime: npm packages are build-time — simpler but every consumer rebuilds on change. Module Federation is runtime — a remote's latest build is live to all hosts on deploy.

Host loads the remote's manifest, then fetches only the needed chunk; both sides share one React instance negotiated by federation.

Module Federation config — host and remote

The remote exposes a component at a stable key; the host maps that key to a CDN URL. Both declare React as a singleton so one copy runs in the page.

ModuleFederationPlugin — host and remote (Webpack 5)js
// remote/webpack.config.js — the "catalog" microfrontend
const { ModuleFederationPlugin } = require("webpack").container;

module.exports = {
  output: { publicPath: "auto" },
  plugins: [
    new ModuleFederationPlugin({
      name: "catalog",
      filename: "remoteEntry.js",
      exposes: {
        "./ProductCard": "./src/components/ProductCard",
      },
      shared: {
        react: { singleton: true, requiredVersion: "^18.0.0" },
        "react-dom": { singleton: true, requiredVersion: "^18.0.0" },
      },
    }),
  ],
};

// host/webpack.config.js — the shell app
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: "shell",
      remotes: {
        catalog: "catalog@https://cdn.example.com/catalog/remoteEntry.js",
      },
      shared: {
        react: { singleton: true, requiredVersion: "^18.0.0" },
        "react-dom": { singleton: true, requiredVersion: "^18.0.0" },
      },
    }),
  ],
};

The host imports catalog/ProductCard via React.lazy; Webpack fetches remoteEntry.js at runtime, then the component chunk only when it first renders.

Tradeoffs

Pros

  • Teams deploy independently — no cross-team coordination per release.
  • Runtime integration: consumers see remote changes without rebuilding.
  • Shared singletons prevent duplicate React or router instances when configured correctly.
  • A crashing remote can be isolated behind an error boundary.

Cons

  • Version-skew in shared deps causes subtle runtime bugs.
  • Cold-load waterfall: host fetches remoteEntry.js, then chunks — adds latency.
  • Every remote is a separate CDN deployment to monitor and version.
  • Local dev needs all remotes running or mocked; DX degrades fast.

Version-skew in shared singletons

If host requires React 18.3 and a remote ships 18.2, federation picks the higher compatible version. If versions are truly incompatible, the remote loads its own copy — doubling React in the page and breaking hooks context. Both sides must declare the same dep in shared with matching requiredVersion ranges, or federation cannot negotiate a single instance.

Interview angle

Focus on the runtime mechanism and failure modes, not config syntax. Explain host/remote, shared singletons, and version-skew. Contrast build-time (npm packages) vs runtime integration. Name Next.js Multi-Zones as a simpler alternative for full framework isolation.

Soundbite: "Module Federation lets teams deploy independently; the risk is version-skew in shared singletons and a cold-load waterfall."

Key terms

Host
The app that consumes remote modules at runtime; declares `remotes` in its federation config.
Remote
A separately deployed build that exposes modules via `exposes` and a `remoteEntry.js` manifest.
exposes
Federation config key mapping a public name to an internal module path the remote makes consumable.
shared singleton
A dep declared `singleton: true` so federation loads one copy across all host/remote boundaries.
Multi-Zones
Next.js feature routing separate Next.js apps by URL prefix via a reverse proxy; no shared JS runtime.

Further reading

Search fearchitect

Jump to a topic, mode, or action.