Skip to main content

Module Federation setup

The shell uses @module-federation/vite (the official MF2 runtime plugin), not @originjs/vite-plugin-federation. The MF2 plugin performs proper runtime shared-version resolution so singletons (React, React DOM, Firebase) genuinely stay single across the host and all remotes.

Mandatory build settings​

  • Build target esnext — the plugin emits top-level await; any lower target breaks the build.
  • Async bootstrap boundary — src/index.ts does import('./bootstrap.tsx') so the shared scope is populated before any shared module is consumed.

Shared singletons​

All shared singletons use the full object form (never the shorthand array). Both the shell host and every MFE remote must declare the exact same set:

shared: {
react: { singleton: true, requiredVersion: '^18.3.1', strictVersion: true },
'react-dom': { singleton: true, requiredVersion: '^18.3.1', strictVersion: true },
'react/jsx-runtime': { singleton: true, requiredVersion: '^18.3.1' },
'firebase/app': { singleton: true, requiredVersion: '^12.0.0' },
'firebase/auth': { singleton: true, requiredVersion: '^12.0.0' },
},

Every Firebase subpath used across the shell and a remote must be declared separately — omitting one causes it to be bundled into the remote chunk, which produces double Firebase initialisation and the FirebaseApp named 'DEFAULT' already exists error.

Independent deployment​

Remotes are referenced by URL. Each microfrontend exposes a single ./App entry point (a MicrofrontendMount). A product team ships a new remote remoteEntry.js to its own URL; the shell picks it up on the next page load with no shell rebuild. The only coordination needed is when the SDK contract changes in a breaking way — that is a semver'd API change.

Verifying no duplicated React​

Use rollup-plugin-visualizer to confirm React is absent from remote chunks, and pnpm why react react-dom firebase in each workspace package to confirm the resolved versions before configuring requiredVersion ranges.