An official Vercel example demonstrating production-ready Module Federation microfrontend architecture using Webpack's Module Federation technology.
This comprehensive example showcases how to build and deploy a Module Federation microfrontend application using @vercel/microfrontends with Module Federation and Next.js Pages Router. Learn how to architect independent, deployable frontend applications that share code at runtime while maintaining team autonomy and deployment independence.
Deploy each microfrontend independently to experience the full power of distributed development:
This example demonstrates real-world Module Federation patterns and best practices:
- π Module Federation: Share code between applications at runtime using Webpack's Module Federation
- ποΈ Microfrontend Architecture: Build independent applications that compose into a unified experience
- β‘ Runtime Code Sharing: Dynamically load and share components between applications
- π¦ Federated Components: Expose and consume React components across application boundaries
- π Independent Deployments: Deploy each microfrontend without affecting others
- π― Team Autonomy: Enable teams to work independently while sharing code seamlessly
Module Federation is a Webpack technology that enables multiple separate builds to form a single application. Unlike traditional microfrontends that communicate through URLs, Module Federation allows:
- Runtime Code Sharing: Import components from other applications at runtime
- Shared Dependencies: Efficiently share libraries like React between applications
- Dynamic Imports: Load federated modules on-demand for optimal performance
- Version Management: Handle different versions of shared dependencies automatically
- Build-time Safety: TypeScript support and compile-time checks for federated modules
This example implements a Module Federation architecture where components are shared at runtime:
-
Root Application (
apps/root/
)- Acts as the shell application and Module Federation container
- Dynamically imports components from content and navigation remotes
- Orchestrates the overall application layout and routing
- Configures federated remotes and manages dependencies
-
Content Application (
apps/content/
)- Exposes content-related components through Module Federation
- Provides federated page components that can be consumed by other applications
- Maintains its own styling and component logic
-
Navigation Application (
apps/navigation/
)- Exposes navigation components (header and footer) through Module Federation
- Provides reusable navigation components for the entire application
- Manages navigation state and user interactions
-
Shared Packages (
packages/
)- Common TypeScript configurations
- Shared ESLint rules and formatting standards
- Ensures consistency across all applications
Ensure you have the following installed:
- Node.js 20.x or later
- pnpm 9.4.0 (recommended package manager)
- Git for version control
-
Clone the repository:
git clone https://github.com/vercel-labs/microfrontends-nextjs-pages-module-federation.git cd microfrontends-nextjs-pages-module-federation
-
Install dependencies:
pnpm install
-
Start the development environment:
pnpm dev
This command starts all applications simultaneously:
- Root app: http://localhost:3024 (main application)
- Content app: http://localhost:3025 (content microfrontend)
- Navigation app: http://localhost:3026 (navigation microfrontend)
-
Access the application: Open http://localhost:3024 in your browser to see the federated application where components from different microfrontends are composed together.
microfrontends-nextjs-pages-module-federation/
βββ apps/
β βββ root/ # Shell application (Module Federation container)
β β βββ pages/ # Next.js Pages Router
β β β βββ index.tsx # Composes federated components
β β βββ microfrontends.json # Routing configuration
β β βββ next.config.js # Next.js + Module Federation config
β β βββ global.d.ts # TypeScript declarations for federated modules
β β
β βββ content/ # Content microfrontend (Module Federation remote)
β β βββ pages/
β β β βββ _app.tsx # Application wrapper (exposed)
β β β βββ _content/
β β β βββ index.tsx # Content page component (exposed)
β β βββ next.config.js # Exposes components via Module Federation
β β
β βββ navigation/ # Navigation microfrontend (Module Federation remote)
β βββ pages/
β β βββ _app.tsx # Application wrapper (exposed)
β β βββ _navigation/
β β βββ header/
β β β βββ index.tsx # Header component (exposed)
β β βββ footer/
β β βββ index.tsx # Footer component (exposed)
β βββ next.config.js # Exposes navigation components
β
βββ packages/
β βββ eslint-config-custom/ # Shared linting configuration
β βββ ts-config/ # Shared TypeScript configuration
β
βββ package.json # Root package.json with workspaces
βββ pnpm-workspace.yaml # PNPM workspace configuration
βββ turbo.json # Turborepo build pipeline
This file defines how microfrontends are discovered and routed:
{
"applications": {
"microfrontends-nextjs-pages-federation-root": {
"development": {
"fallback": "microfrontends-nextjs-pages-federation-root.vercel.app"
}
},
"microfrontends-nextjs-pages-federation-content": {
"routing": [{ "paths": ["/_content/:path*"] }]
},
"microfrontends-nextjs-pages-federation-navigation": {
"routing": [{ "paths": ["/_navigation/:path*"] }]
}
}
}
Each application has its own Next.js configuration enhanced with Module Federation:
Root Application (Container):
// apps/root/next.config.js
import { NextFederationPlugin } from '@module-federation/nextjs-mf';
const nextConfig = {
webpack(config, { isServer }) {
config.plugins.push(
new NextFederationPlugin({
name: 'root',
filename: 'static/chunks/remoteEntry.js',
remotes: {
content: `_mf_content@http://localhost:3025/_next/static/${isServer ? 'ssr' : 'chunks'}/remoteEntry.js`,
navigation: `_mf_navigation@http://localhost:3026/_next/static/${isServer ? 'ssr' : 'chunks'}/remoteEntry.js`,
},
}),
);
return config;
},
};
Remote Applications (Content & Navigation):
// apps/content/next.config.js
import { NextFederationPlugin } from '@module-federation/nextjs-mf';
const nextConfig = {
webpack(config, { isServer }) {
config.plugins.push(
new NextFederationPlugin({
name: '_mf_content',
filename: `static/${isServer ? 'ssr' : 'chunks'}/remoteEntry.js`,
exposes: {
'./page': './pages/_content/index.tsx',
'./app': './pages/_app.tsx',
},
}),
);
return config;
},
};
The magic happens through Webpack's Module Federation technology:
Remote applications expose their components through Module Federation:
// Each remote defines what components to expose
exposes: {
'./page': './pages/_content/index.tsx', // Content page
'./header': './pages/_navigation/header/index.tsx', // Header component
'./footer': './pages/_navigation/footer/index.tsx', // Footer component
'./app': './pages/_app.tsx' // App wrapper
}
The root application dynamically imports these components at runtime:
// apps/root/pages/index.tsx
import NavigationApp from 'navigation/app';
import Header from 'navigation/header';
import Footer from 'navigation/footer';
import Page from 'content/page';
import ContentApp from 'content/app';
export default function Home() {
return (
<>
<NavigationApp Component={Header} />
<ContentApp Component={Page} />
<NavigationApp Component={Footer} />
</>
);
}
Module Federation enables:
- Shared Dependencies: React and other libraries are shared between applications
- Dynamic Loading: Components are loaded on-demand at runtime
- Version Management: Handles different dependency versions automatically
- Type Safety: TypeScript support with federated module declarations
In production, each microfrontend is deployed independently, and Module Federation resolves the federated modules from their respective URLs.
You can develop microfrontends in isolation:
# Work on the root application only
cd apps/root
pnpm dev
# Work on the content application only
cd apps/content
pnpm dev
# Work on the navigation application only
cd apps/navigation
pnpm dev
# Build all applications
pnpm build
# Run linting across all apps
pnpm lint
# Type check all applications
pnpm typecheck
# Run all quality checks
pnpm checks
- Create the component in your remote application
- Expose it through Module Federation in
next.config.js
:exposes: { './newComponent': './path/to/component.tsx' }
- Add TypeScript declarations in the container app's
global.d.ts
:declare module 'remoteName/newComponent' { const Component: React.ComponentType; export default Component; }
- Import and use in the container application:
import NewComponent from 'remoteName/newComponent';
Each microfrontend can be deployed independently, enabling:
- Faster deployments: Only the changed microfrontend needs redeployment
- Reduced risk: Deployments are isolated and can't break other parts
- Team autonomy: Teams can deploy on their own schedule
- Rollback flexibility: Roll back individual microfrontends without affecting others
Each application includes optimized Vercel configuration:
- Framework detection: Automatic Next.js optimization
- Build settings: Turborepo-aware build commands with Module Federation support
- Environment variables: Proper environment isolation
- Edge functions: Optimal performance at the edge
- Shared TypeScript configuration ensures type safety across all federated modules
- Common ESLint rules maintain code quality standards
- Unified prettier configuration for consistent formatting
- Turborepo orchestrates builds efficiently with caching
- Module Federation optimizes shared dependencies automatically
- Independent builds enable faster CI/CD pipelines
- Shared component patterns across federated modules
- Consistent design tokens and styling approach
- Federated components maintain design system compliance
- Code splitting at the microfrontend level with Module Federation
- Shared chunk optimization for common dependencies
- Runtime loading optimization for federated modules
The project includes comprehensive TypeScript support:
// apps/root/global.d.ts
declare module 'navigation/header' {
const Header: React.ComponentType;
export default Header;
}
declare module 'navigation/footer' {
const Footer: React.ComponentType;
export default Footer;
}
declare module 'content/page' {
const Page: React.ComponentType;
export default Page;
}
Development builds include the Vercel Toolbar for enhanced debugging:
- Visual indicators of federated module boundaries
- Performance metrics for federated components
- Real-time module loading analytics
Built-in error handling for federated components:
- Graceful degradation when remote modules fail to load
- Isolated error reporting per microfrontend
- Fallback components for improved user experience
Module Federation loading errors:
# Ensure all applications are running
pnpm dev
# Check that remoteEntry.js files are accessible
curl http://localhost:3025/_next/static/chunks/remoteEntry.js
TypeScript errors with federated modules:
# Verify TypeScript declarations in global.d.ts
# Ensure module names match the federation configuration
Build failures:
# Run type checking to identify issues
pnpm typecheck
# Verify all federated modules are built correctly
pnpm build
Port conflicts during development:
# Kill processes using the required ports
npx kill-port 3024 3025 3026
pnpm dev
This example uses Module Federation for runtime code sharing, which differs from multi-zone architecture:
Feature | Module Federation | Multi-Zone |
---|---|---|
Code Sharing | Runtime component sharing | URL-based routing |
Bundle Size | Shared dependencies | Independent bundles |
Integration | Component-level integration | Page-level integration |
Complexity | Higher (runtime loading) | Lower (URL routing) |
Use Case | Shared UI components | Independent applications |
Choose Module Federation when you need to share React components between applications. Choose multi-zone when you need independent applications with URL-based routing.
π Documentation