Next.js模块联邦开发报错:TypeError: dispatcher is null及Hook调用异常
问题排查:Next.js模块联邦开发中的多错误问题
遇到的错误现象
- 多次代码重建后触发
TypeError: dispatcher is null - 浏览器控制台弹出
Invalid hook call警告,提示Hook只能在函数组件内部调用,可能原因包括React与渲染器版本不匹配、违反Hook规则、存在多份React副本 - 浏览器控制台出现
Warning: Cannot update a component (HotReload) while rendering a different component (wL)警告 - VSCode终端显示
No ModuleFederationPlugin(s) found
相关代码
page.js
/// <reference types="@module-federation/nextjs-mf/src/include-defaults" /> 'use client' import dynamic from "next/dynamic" const Footer = dynamic(() => import("container/App"), { ssr: false }); export default function Home() { return ( <> <h1> Welcome to the Shop app port: 3001 </h1> {Footer ? <Footer /> : <div>Loading...</div>} </> ) }
next.config.js
const NextFederationPlugin = require("@module-federation/nextjs-mf"); const path = require("path"); const webpack = require('webpack'); const shared = ["react", "react-dom", "next/dynamic"] const ASSET_PATH = process.env.ASSET_PATH || '/'; module.exports = { reactStrictMode: true, pageExtensions: ['mdx', 'md', 'jsx', 'js', 'tsx', 'ts'], experimental: { isrMemoryCacheSize: 0, appDir: true, }, webpack(config, options) { const { isServer } = options; config.plugins.push( new NextFederationPlugin({ name: "web-fs", remotes: { container: `container@https://xx-xx-xx-xx.xx.com.br/_next/static/chunks/remoteEntry.js?v=${Date.now()}` }, filename: 'static/chunks/remoteEntry.js', shared: shared, }), new webpack.DefinePlugin({ 'use client': JSON.stringify(true) }) ); const fileLoaderRule = config.module.rules.find((rule) => rule.test?.test?.(".svg") ); config.module.rules.push( { ...fileLoaderRule, test: /\.svg$/i, resourceQuery: /url/, }, { test: /\.svg$/i, issuer: /\.[jt]sx?$/, resourceQuery: { not: /url/ }, use: ["@svgr/webpack"], } ); fileLoaderRule.exclude = /\.svg$/i; return config; }, };
layout.tsx
/// <reference types="@module-federation/nextjs-mf/src/include-defaults" /> 'use client' import "./globals.css"; import { Inter } from "@next/font/google"; import Providers from "./components/Providers"; import CheckLogin from "./components/CheckLogin"; import Footer from "./components/Footer"; import { Suspense } from "react"; export const metadata = { title: "Web Feature Store", }; const inter = Inter({ subsets: ["latin"] }); export default function RootLayout({ children, }: { children: React.ReactNode; }) { console.log("layout"); return ( <html lang="pt"> <body className={inter.className}> <Providers> <CheckLogin /> {children} </Providers> <br /> <footer> <Footer /> </footer> </body> </html> ); }
providers.tsx
"use client"; import { SessionProvider } from "next-auth/react"; import React, { ReactNode } from "react"; interface Props { children: ReactNode; } const Providers = (props: Props) => { console.log("providers"); return <SessionProvider>{props.children}</SessionProvider>; }; export default Providers;
package.json
{ "name": "web-feature-store-v2", "version": "0.1.0", "private": false, "scripts": { "dev": "next dev -p 3000", "build": "next build && npx tailwind -i app/globals.css -o app/tailwind.css", "start": "next start -p 3000", "lint": "next lint" }, "resolutions": { "webpack": "5.1.3" }, "dependencies": { "@chakra-ui/react": "2.6.1", "@emotion/react": "11.10.6", "@emotion/styled": "11.10.6", "@google-cloud/storage": "^7.5.0", "@module-federation/nextjs-mf": "6.7.1", "@mui/icons-material": "^5.14.1", "@mui/material": "^5.14.2", "@mui/x-data-grid": "^6.10.2", "@next-tools/dynamic": "^0.0.11", "@next/font": "13.1.0", "@radix-ui/colors": "^3.0.0-rc.4", "@radix-ui/primitive": "^1.0.1", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dropdown-menu": "^2.0.5", "@react-oauth/google": "^0.11.1", "@reduxjs/toolkit": "^1.9.5", "@tanstack/react-query": "^4.33.0", "@tanstack/react-table": "^8.9.7", "@types/chart.js": "^2.9.40", "@types/node": "20.4.5", "@types/react": "18.2.17", "@types/react-dom": "18.2.7", "axios": "^1.4.0", "bootstrap": "^5.3.1", "chart.js": "^4.4.0", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "dotenv": "^16.3.1", "encoding": "^0.1.13", "env-cmd": "^10.1.0", "eslint": "8.46.0", "eslint-config-next": "13.4.12", "external-remotes-plugin": "^1.0.0", "framer-motion": "^10.16.2", "fs": "^0.0.1-security", "lib-utils-ts": "^2.0.4-stable", "lucide-react": "^0.274.0", "net": "^1.0.2", "next": "13.1.6", "next-auth": "^4.24.7", "next-external-remotes-plugin": "^1.0.4", "react": "^18.2.0", "react-bootstrap": "^2.8.0", "react-chartjs-2": "^5.2.0", "react-dom": "^18.2.0", "react-modal": "^3.16.1", "react-redux": "^8.1.2", "reactjs-popup": "^2.0.6", "reactstrap": "^9.2.0", "sharp": "^0.32.4", "tailwind-merge": "^1.14.0", "tailwindcss-animate": "^1.0.7", "typescript": "5.1.6", "webpack": "^5.75.0", "yarn": "^1.22.22" }, "devDependencies": { "@faker-js/faker": "^8.0.2", "@types/react-modal": "^3.16.0", "autoprefixer": "^10.4.14", "json-loader": "^0.5.7", "postcss": "^8.4.27", "react-router-dom": "^6.14.2", "tailwindcss": "^3.3.3" }, "browser": { "child_process": false, "fs": false, "tls": false } }
问题修复方案
1. 解决多份React副本与Hook调用错误
- 原因:shared配置为数组形式,未强制单例,导致主/远程应用加载多份React;错误通过DefinePlugin定义
use client,破坏React运行时机制 - 修复:
- 修改shared为对象配置,强制单例并指定版本:
const shared = { react: { singleton: true, requiredVersion: "^18.2.0" }, "react-dom": { singleton: true, requiredVersion: "^18.2.0" }, "next/dynamic": { singleton: true } }; - 移除
new webpack.DefinePlugin({ 'use client': JSON.stringify(true) }),use client是Next.js原生指令,无需额外定义
- 修改shared为对象配置,强制单例并指定版本:
2. 修复No ModuleFederationPlugin(s) found警告
- 原因:Next.js 13 App Router下,服务端不需要生成remoteEntry,插件全局添加导致服务端识别异常
- 修复:在webpack配置中仅客户端添加插件:
if (!isServer) { config.plugins.push( new NextFederationPlugin({ name: "web-fs", remotes: { container: `container@https://xx-xx-xx-xx.xx.com.br/_next/static/chunks/remoteEntry.js?v=${Date.now()}` }, filename: 'static/chunks/remoteEntry.js', shared: shared, }) ); }
3. 修复动态组件加载与HotReload警告
- 原因:动态组件
Footer是构造函数,永远为真,手动条件判断无效;热重载时组件更新时机冲突 - 修复:用Suspense包裹动态组件替代手动Loading:
export default function Home() { return ( <> <h1>Welcome to the Shop app port: 3001</h1> <Suspense fallback={<div>Loading...</div>}> <Footer /> </Suspense> </> ) }
4. 修复webpack版本冲突
- 原因:resolutions强制webpack@5.1.3与dependencies中webpack@5.75.0冲突,导致插件加载异常
- 修复:删除resolutions中的webpack配置,运行
yarn install重新安装依赖
内容的提问来源于stack exchange,提问作者douglas siqueira
相关产品推荐
相关产品推荐

