Micro Frontend Guide

Approaches Comparison

ApproachIntegrationIsolationComplexityBest For
Module Federation (Webpack 5)Build-timeShared runtimeMediumReact/Vue apps, tight integration
single-spaRuntimePer-app isolationHighMixed frameworks, legacy migration
Web ComponentsRuntimeShadow DOM isolationLow-MediumFramework-agnostic widgets
iframesRuntimeCompleteLowThird-party integrations
Server-Side CompositionServerCompleteMediumSSR pages, Edge Side Includes

Module Federation (Webpack 5)

// Host app — webpack.config.js const { ModuleFederationPlugin } = require('webpack').container; module.exports = { plugins: [ new ModuleFederationPlugin({ name: 'host', remotes: { // remote-app exposed at this URL checkout: 'checkout@https://checkout.example.com/remoteEntry.js', catalog: 'catalog@https://catalog.example.com/remoteEntry.js', }, shared: { react: { singleton: true, requiredVersion: '^18.0.0' }, 'react-dom': { singleton: true, requiredVersion: '^18.0.0' }, }, }), ], }; // Remote app — webpack.config.js new ModuleFederationPlugin({ name: 'checkout', filename: 'remoteEntry.js', exposes: { './CheckoutFlow': './src/CheckoutFlow', './CartButton': './src/CartButton', }, shared: { react: { singleton: true } }, }) // Usage in host const CheckoutFlow = React.lazy(() => import('checkout/CheckoutFlow'));

Communication Patterns

PatternUse CaseExample
Custom EventsLoose coupling, same-page eventswindow.dispatchEvent(new CustomEvent('cart:add', {detail: item}))
Shared State (Redux)Global state across MFEsSingle store in host, consumed by remotes
URL / Route paramsNavigation dataReact Router or native history API
Props / CallbacksParent-child MFE dataModule Federation exposed component props
BroadcastChannelCross-tab communicationnew BroadcastChannel('app')