This template demonstrates how to use Next.js Pages Router with Module Federation.
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 is a Webpack technology that enables multiple separate builds to form a single application. Unlike traditional microfrontends that communicate through URLs, Module Federation allows:
This example implements a Module Federation architecture where components are shared at runtime:
Root Application (apps/root/
)
Content Application (apps/content/
)
Navigation Application (apps/navigation/
)
Shared Packages (packages/
)
Ensure you have the following installed:
Clone the repository:
git clone https://github.com/vercel-labs/microfrontends-nextjs-pages-module-federation.gitcd microfrontends-nextjs-pages-module-federation
Install dependencies:
pnpm install
Start the development environment:
pnpm dev
This command starts all applications simultaneously:
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
microfrontends.json
This file defines how microfrontends are discovered and routed:
Module Federation Configuration
{"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.jsimport { 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.jsimport { 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 exposeexposes: {'./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.tsximport 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:
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 onlycd apps/rootpnpm dev# Work on the content application onlycd apps/contentpnpm dev# Work on the navigation application onlycd apps/navigationpnpm dev
# Build all applicationspnpm build# Run linting across all appspnpm lint# Type check all applicationspnpm typecheck# Run all quality checkspnpm checks
next.config.js
:
exposes: {'./newComponent': './path/to/component.tsx'}
global.d.ts
:
declare module 'remoteName/newComponent' {const Component: React.ComponentType;export default Component;}
import NewComponent from 'remoteName/newComponent';
Each microfrontend can be deployed independently, enabling:
Each application includes optimized Vercel configuration:
The project includes comprehensive TypeScript support:
// apps/root/global.d.tsdeclare 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:
Built-in error handling for federated components:
Module Federation loading errors:
# Ensure all applications are runningpnpm dev# Check that remoteEntry.js files are accessiblecurl 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 issuespnpm typecheck# Verify all federated modules are built correctlypnpm build
Port conflicts during development:
# Kill processes using the required portsnpx kill-port 3024 3025 3026pnpm 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.
This template demonstrates how to use Next.js Pages Router with Module Federation.
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 is a Webpack technology that enables multiple separate builds to form a single application. Unlike traditional microfrontends that communicate through URLs, Module Federation allows:
This example implements a Module Federation architecture where components are shared at runtime:
Root Application (apps/root/
)
Content Application (apps/content/
)
Navigation Application (apps/navigation/
)
Shared Packages (packages/
)
Ensure you have the following installed:
Clone the repository:
git clone https://github.com/vercel-labs/microfrontends-nextjs-pages-module-federation.gitcd microfrontends-nextjs-pages-module-federation
Install dependencies:
pnpm install
Start the development environment:
pnpm dev
This command starts all applications simultaneously:
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
microfrontends.json
This file defines how microfrontends are discovered and routed:
Module Federation Configuration
{"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.jsimport { 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.jsimport { 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 exposeexposes: {'./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.tsximport 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:
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 onlycd apps/rootpnpm dev# Work on the content application onlycd apps/contentpnpm dev# Work on the navigation application onlycd apps/navigationpnpm dev
# Build all applicationspnpm build# Run linting across all appspnpm lint# Type check all applicationspnpm typecheck# Run all quality checkspnpm checks
next.config.js
:
exposes: {'./newComponent': './path/to/component.tsx'}
global.d.ts
:
declare module 'remoteName/newComponent' {const Component: React.ComponentType;export default Component;}
import NewComponent from 'remoteName/newComponent';
Each microfrontend can be deployed independently, enabling:
Each application includes optimized Vercel configuration:
The project includes comprehensive TypeScript support:
// apps/root/global.d.tsdeclare 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:
Built-in error handling for federated components:
Module Federation loading errors:
# Ensure all applications are runningpnpm dev# Check that remoteEntry.js files are accessiblecurl 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 issuespnpm typecheck# Verify all federated modules are built correctlypnpm build
Port conflicts during development:
# Kill processes using the required portsnpx kill-port 3024 3025 3026pnpm 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.