Micro Frontend
Micro frontends split a web app into independently built and deployed pieces owned by separate teams, composed via an app shell or server-side stitching. They enable team autonomy and incremental modernization at the cost of integration and consistency overhead.
The micro frontend pattern extends microservice thinking to the browser: a single web application is split into smaller, independently developed and deployed frontends, each owned by a different team, then composed into one user experience. The goal is to scale frontend development across many teams and to let each ship on its own cadence.
How It Works
Each micro frontend covers a vertical slice of the UI — a product catalog, a checkout flow, an account area — and is built, tested, and deployed independently. Composition happens by several mechanisms: build-time integration (packages assembled into one bundle), server-side composition (a layout service stitches fragments), run-time composition via an app shell that loads remotes (Module Federation in Webpack/Vite), or simple iframe/Web Component embedding. A shell or container handles routing and shared concerns like authentication and a common design system.
Teams agree on contracts: shared design tokens, cross-app events, and routing conventions. Isolation matters — CSS scoping and avoiding global state collisions keep one micro frontend from breaking another.
When to Use It
Use micro frontends when a large frontend is maintained by many teams that need autonomy and independent release cycles, or when incrementally modernizing a legacy UI — a strangler-fig approach where new micro frontends replace old pages one at a time (e.g. migrating AngularJS or jQuery screens to React piece by piece). They suit big, long-lived products, not small apps.
Trade-offs
The cost is real complexity. Duplicate framework runtimes inflate bundle size unless shared dependencies are carefully managed. Consistent UX requires a shared design system and governance. Run-time integration adds failure modes and performance overhead, and end-to-end testing across independently deployed pieces is hard. For a single team or a small app, a well-structured monolith (a "modular monolith" frontend) is simpler and usually better.
Related Patterns
Micro frontends mirror microservices and often pair with a backend-for-frontend per team. Island architecture is a lighter way to ship independent interactive units within one site. The strangler-fig pattern guides incremental replacement of a legacy UI. The sidecar concept inspires shared cross-cutting tooling around each frontend.
Example
// Host app shell using Module Federation (Webpack)
const Catalog = React.lazy(() => import('catalog/App'));
const Checkout = React.lazy(() => import('checkout/App'));
function Shell() {
return (
<Suspense fallback={<Spinner />}>
<Routes>
<Route path="/catalog/*" element={<Catalog />} />
<Route path="/checkout/*" element={<Checkout />} />
</Routes>
</Suspense>
);
}
The shell loads each team's independently deployed remote at run time, composing them into one application.