Next.js 13集成module federation遇'client-only'错误如何解决
问题描述
在Next.js 13.4.4中使用App Router结合@module-federation/nextjs-mf实现微前端时,添加Webpack配置后触发以下错误:
./node_modules\next\dist\compiled\client-only\error.js 'client-only' cannot be imported from a Server Component module. It should only be used from a Client Component. Import trace for the requested module: ./node_modules\next\dist\compiled\client-only\error.js ./node_modules\styled-jsx\dist\index\index.js ./node_modules\styled-jsx\style.js ./node_modules@module-federation\nextjs-mf\src\include-defaults.js ./src\app\page.js
相关配置与代码
next.config.js
const { NextFederationPlugin } = require('@module-federation/nextjs-mf'); const remotes = (isServer) => { const location = isServer ? 'ssr' : 'chunks'; return { remoteApp: `remoteApp@http://localhost:3001/_next/static/${location}/remoteEntry.js` }; } const nextConfig = { reactStrictMode: true, experimental: { esmExternals: false, }, webpack(config, { isServer }) { config.plugins.push( new NextFederationPlugin({ name: 'host', filename: 'static/chunks/remoteEntry.js', remotes: remotes(isServer), exposes: {}, shared: {}, extraOptions:{ automaticAsyncBoundary: true } }) ); return config; }, } module.exports = nextConfig
宿主页面代码(src/pages/hostPage.js)
"use client" const Remote = dynamic( () => import('remoteApp/NewPage').then((mod) => mod.NewPage), { ssr: false, } ); export function Home() { return ( <main className="flex min-h-screen flex-col items-center justify-between p-24"> <h1 className='text-white'>This is host</h1> <Remote /> </main> ) } export default Home;
依赖版本
"dependencies": { "next": "13.4.4", "react": "18.2.0", "react-dom": "18.2.0", "tailwindcss": "3.3.2", "@module-federation/utilities": "1.7.3", "@module-federation/nextjs-mf": "6.4.0" }, "devDependencies": { "webpack": "^5.76.2" }
解决方案
1. 将宿主入口页面标记为客户端组件
错误核心是src/app/page.js默认是服务器组件,但@module-federation/nextjs-mf内部代码引入了仅支持客户端的client-only模块。在src/app/page.js顶部添加客户端标记:
// src/app/page.js "use client" import Home from '../pages/hostPage'; export default function RootPage() { return <Home />; }
2. 确保远程组件适配客户端渲染
如果远程应用使用App Router,暴露的组件也需要添加"use client"指令,避免服务器组件被客户端宿主导入时出现冲突。
3. 服务器端构建排除客户端依赖
在Webpack配置中,针对服务器端构建排除styled-jsx相关依赖(服务器端无需加载该客户端样式工具):
webpack(config, { isServer }) { if (isServer) { config.externals.push('styled-jsx/style'); } config.plugins.push( new NextFederationPlugin({ // 原有配置保持不变 }) ); return config; },
4. 验证异步边界配置
确认extraOptions.automaticAsyncBoundary: true生效,该配置会自动为远程模块添加异步边界隔离服务端与客户端代码。若问题仍存在,可手动为远程组件添加加载状态:
const Remote = dynamic( () => import('remoteApp/NewPage').then((mod) => mod.NewPage), { ssr: false, loading: () => <div>加载中...</div> } );
内容的提问来源于stack exchange,提问作者Pourya Tak
相关产品推荐
相关产品推荐

