Day 30: Micro-Frontends & Module Federation Basics
Understand why and how large orgs split one frontend into independently deployable pieces, and the core mechanics of Webpack Module Federation.
Study
Concepts
The problem micro-frontends solve: team autonomy at scale
A single large SPA owned by many teams eventually hits a coordination wall — every team's changes go through the same build, the same deploy, and the same release calendar, and a bug in one team's code can block everyone else's release. Micro-frontends split the UI into independently BUILT and independently DEPLOYED pieces (often owned by different teams, sometimes different frameworks), composed together at runtime into what still looks like one seamless application to the end user.
This is an organizational scaling tool more than a performance one — for a small team or app, it adds real complexity (shared design system, cross-app state, duplicated dependencies) without a matching benefit. The right trigger is "multiple independent teams shipping on independent schedules to the same product", not "the codebase feels big".
Module Federation: runtime code sharing across builds
Webpack 5's Module Federation lets one build ("remote") expose specific modules (a component, a whole page) that another build ("host") imports and loads AT RUNTIME over the network, as if it were a normal dynamic import — the host never bundles the remote's code at build time; it fetches it live. Shared dependencies (React, a design system) can be configured as `singleton: true` so multiple micro-frontends reuse ONE instance of React on the page instead of shipping (and running) duplicate copies.
The main failure modes to design around: version skew between shared dependencies (React 18 host loading a React 17 remote breaks hooks), inconsistent styling/UX across independently-built pieces, and harder end-to-end debugging since a bug can originate in code your team does not own or control the deploy of.
See It
Visualizations
Visualization
Host app composing two independently deployed remotes
Build It
Code Examples
Module Federation config — a remote exposing a component
// checkout-app/webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'checkout',
filename: 'remoteEntry.js',
exposes: {
'./CheckoutWidget': './src/CheckoutWidget',
},
shared: {
react: { singleton: true, requiredVersion: '^19.0.0' },
'react-dom': { singleton: true, requiredVersion: '^19.0.0' },
},
}),
],
};Host config + runtime usage of the remote
// shell-app/webpack.config.js
new ModuleFederationPlugin({
name: 'shell',
remotes: {
checkout: 'checkout@https://checkout.example.com/remoteEntry.js',
},
shared: { react: { singleton: true }, 'react-dom': { singleton: true } },
});
// shell-app/src/App.jsx — loaded like a normal lazy component
const CheckoutWidget = React.lazy(() => import('checkout/CheckoutWidget'));
function App() {
return (
<Suspense fallback={<Spinner />}>
<CheckoutWidget /> {/* fetched over the network at runtime */}
</Suspense>
);
}Remember
Key Takeaways
- Micro-frontends solve organizational scale (many independent teams/deploys), not raw performance — evaluate the tradeoff honestly.
- Module Federation lets a host import a remote's code at RUNTIME, over the network — no shared build step required.
- shared: { react: { singleton: true } } avoids shipping and running multiple copies of the same library.
- Version skew between host and remote shared dependencies is the #1 real production failure mode — pin and coordinate carefully.
- A consistent design system across remotes is required to keep the composed app feeling like one product, not several.
Do It
Practice
- 1Set up two small Webpack apps locally with Module Federation: one exposing a Counter component, one hosting and rendering it.
- 2Deliberately mismatch React versions between host and remote (non-singleton) and observe the resulting runtime error.
- 3Write a short design doc (half a page) arguing for or against micro-frontends for a hypothetical 40-engineer product team.