如何在Next.js 14(TypeScript)中使用Module Federation?求实现示例
Next.js 14 + TypeScript 实现 Module Federation 案例
下面是一套完整的主应用(Host)和远程应用(Remote)实现方案,基于Next.js 14 App Router + TypeScript:
一、初始化项目
创建两个Next.js项目,均启用TypeScript:
# 创建远程应用 npx create-next-app@latest mf-remote --typescript --eslint --tailwind --app --no-src-dir --import-alias "@/*" # 创建主应用 npx create-next-app@latest mf-host --typescript --eslint --tailwind --app --no-src-dir --import-alias "@/*"
二、配置远程应用(mf-remote)
- 安装依赖
cd mf-remote npm install @module-federation/nextjs-mf @module-federation/utilities
- 修改
next.config.ts
import type { NextConfig } from 'next' import { NextFederationPlugin } from '@module-federation/nextjs-mf' const nextConfig: NextConfig = { webpack(config, options) { // 仅在客户端打包时配置Module Federation if (!options.isServer) { config.plugins.push( new NextFederationPlugin({ name: 'remoteApp', // 远程应用标识 filename: 'static/chunks/remoteEntry.js', // 远程入口文件路径 exposes: { // 暴露的组件路径(相对项目根目录) './Button': './components/Button.tsx', './Counter': './components/Counter.tsx', }, shared: { // 共享依赖,避免重复打包 react: { singleton: true, eager: true }, 'react-dom': { singleton: true, eager: true }, }, }) ) } return config }, } export default nextConfig
- 编写暴露的组件
在项目根目录创建components文件夹,添加两个组件:
components/Button.tsx:
'use client' import type { ReactNode } from 'react' interface ButtonProps { onClick: () => void children: ReactNode variant?: 'primary' | 'secondary' } export const Button = ({ onClick, children, variant = 'primary' }: ButtonProps) => { const baseStyle = 'px-4 py-2 rounded font-medium transition-colors' const variantStyle = variant === 'primary' ? 'bg-blue-600 text-white hover:bg-blue-700' : 'bg-gray-200 text-gray-800 hover:bg-gray-300' return ( <button onClick={onClick} className={`${baseStyle} ${variantStyle}`}> {children} </button> ) }
components/Counter.tsx:
'use client' import { useState } from 'react' import { Button } from './Button' export const Counter = () => { const [count, setCount] = useState(0) return ( <div className="flex flex-col gap-3 items-center"> <p className="text-xl">远程计数器:{count}</p> <div className="flex gap-2"> <Button onClick={() => setCount(count - 1)} variant="secondary">-</Button> <Button onClick={() => setCount(count + 1)}>+</Button> </div> </div> ) }
三、配置主应用(mf-host)
- 安装依赖
cd mf-host npm install @module-federation/nextjs-mf @module-federation/utilities
- 修改
next.config.ts
import type { NextConfig } from 'next' import { NextFederationPlugin } from '@module-federation/nextjs-mf' const nextConfig: NextConfig = { webpack(config, options) { if (!options.isServer) { config.plugins.push( new NextFederationPlugin({ name: 'hostApp', // 主应用标识 remotes: { // 映射远程应用:[标识]@[远程应用地址]/[入口文件路径] remoteApp: 'remoteApp@http://localhost:3001/static/chunks/remoteEntry.js', }, shared: { react: { singleton: true, eager: true }, 'react-dom': { singleton: true, eager: true }, }, }) ) } return config }, } export default nextConfig
- 添加TypeScript类型声明
在项目根目录创建types/remoteApp.d.ts,让TypeScript识别远程组件类型:
declare module 'remoteApp/Button' { import type { ReactNode } from 'react' interface ButtonProps { onClick: () => void children: ReactNode variant?: 'primary' | 'secondary' } export const Button: React.FC<ButtonProps> } declare module 'remoteApp/Counter' { export const Counter: React.FC }
- 在主应用中使用远程组件
修改app/page.tsx:
'use client' import { Button } from 'remoteApp/Button' import { Counter } from 'remoteApp/Counter' export default function Home() { const handleLocalClick = () => { alert('主应用按钮被点击!') } return ( <main className="min-h-screen p-8 flex flex-col gap-8"> <h1 className="text-3xl font-bold">Next.js 14 Module Federation 主应用</h1> <section className="p-4 border rounded-lg"> <h2 className="text-xl font-semibold mb-3">本地按钮组件</h2> <Button onClick={handleLocalClick} variant="primary">本地按钮</Button> </section> <section className="p-4 border rounded-lg"> <h2 className="text-xl font-semibold mb-3">远程计数器组件</h2> <Counter /> </section> </main> ) }
四、运行测试
- 启动远程应用(指定端口3001)
cd mf-remote npm run dev -p 3001
- 启动主应用
cd mf-host npm run dev
访问http://localhost:3000,即可看到主应用加载并使用远程组件的效果。
内容的提问来源于stack exchange,提问作者Corepex
相关产品推荐
相关产品推荐

