Webpack 5 Module Federation报错:容器中模块不存在,求排查方案
问题描述
我尝试用Single SPA结合Webpack 5的Module Federation构建远程/宿主模式的微前端(MFE),但宿主应用抛出“Module doesn't exists in the container”错误。以下是相关配置代码:
远程应用Webpack配置
const HtmlWebPackPlugin = require("html-webpack-plugin"); const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); const deps = require("./package.json").dependencies; module.exports = { output: { publicPath: "http://localhost:3001/", }, resolve: { extensions: [".tsx", ".ts", ".jsx", ".js", ".json"], }, devServer: { port: 3001, historyApiFallback: true, }, module: { rules: [ { test: /\.m?js/, type: "javascript/auto", resolve: { fullySpecified: false, }, }, { test: /\.(css|s[ac]ss)$/i, use: ["style-loader", "css-loader", "postcss-loader"], }, { test: /\.(ts|tsx|js|jsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", }, }, { test: /\.(png|jpg|jpeg|svg)$/, exclude: /node_modules/, use: { loader: "file-loader", }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: "mfe", filename: "remoteEntry.js", remotes: {}, exposes: { "/EventListing":"./src/Events/EventListing", }, shared: { ...deps, react: { singleton: true, requiredVersion: deps.react, }, "react-dom": { singleton: true, requiredVersion: deps["react-dom"], }, }, }), new HtmlWebPackPlugin({ template: "./src/index.html", }), ], };
宿主应用Webpack配置
const HtmlWebPackPlugin = require("html-webpack-plugin"); const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); const deps = require("./package.json").dependencies; module.exports = { output: { publicPath: "http://localhost:3000/", }, resolve: { extensions: [".tsx", ".ts", ".jsx", ".js", ".json"], }, devServer: { port: 3000, historyApiFallback: true, }, module: { rules: [ { test: /\.m?js/, type: "javascript/auto", resolve: { fullySpecified: false, }, }, { test: /\.(css|s[ac]ss)$/i, use: ["style-loader", "css-loader", "postcss-loader"], }, { test: /\.(ts|tsx|js|jsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: "host", filename: "remoteEntry.js", remotes: { "mfe":"mfe@http://localhost:3001/remoteEntry.js" }, exposes: {}, shared: { ...deps, react: { singleton: true, requiredVersion: deps.react, }, "react-dom": { singleton: true, requiredVersion: deps["react-dom"], }, }, }), new HtmlWebPackPlugin({ template: "./src/index.html", }), ], };
宿主应用index.tsx代码
import { registerApplication, start } from 'single-spa'; import './index.d'; registerApplication( 'event-listing', () => import('mfe/EventListing'), location => location.pathname.startsWith('/') ); start();
宿主应用HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>host</title> </head> <body> <div id="single-spa-application:event-listing"></div> </body> </html>
问题修复方案
1. 修正暴露模块的路径格式
远程应用exposes配置中,暴露路径开头的斜杠会导致宿主引用路径不匹配。修改远程Webpack配置的exposes:
exposes: { "./EventListing": "./src/Events/EventListing", },
2. 确保远程模块符合Single SPA生命周期规范
Single SPA要求微前端必须导出bootstrap、mount、unmount三个生命周期函数,检查EventListing文件是否正确实现:
import React from 'react'; import ReactDOM from 'react-dom/client'; import EventListingComponent from './EventListingComponent'; export const bootstrap = async () => { // 初始化逻辑,如预加载资源 }; export const mount = async (props: any) => { const root = ReactDOM.createRoot( document.getElementById(props.domElementId) as HTMLElement ); root.render(<EventListingComponent />); }; export const unmount = async (props: any) => { const root = ReactDOM.createRoot( document.getElementById(props.domElementId) as HTMLElement ); root.unmount(); };
3. 确保远程Entry文件加载完成
可在宿主HTML中手动引入远程Entry,避免加载时序问题:
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>host</title> <script src="http://localhost:3001/remoteEntry.js"></script> </head>
或用Single SPA的loadScript动态加载:
import { registerApplication, start, loadScript } from 'single-spa'; registerApplication( 'event-listing', async () => { await loadScript('http://localhost:3001/remoteEntry.js'); return import('mfe/EventListing'); }, location => location.pathname.startsWith('/') ); start();
4. 验证远程模块路径正确性
确认./src/Events/EventListing路径指向的文件存在,且是导出生命周期函数的入口文件(而非单纯组件)。若文件结构为src/Events/EventListing/index.tsx,需调整路径为./src/Events/EventListing/index,或确保Webpack能自动解析目录入口。
5. 对齐共享依赖版本
检查宿主与远程应用的react、react-dom版本是否一致,确保Webpackshared配置中的requiredVersion与package.json中的依赖版本匹配,避免版本冲突导致加载失败。
内容的提问来源于stack exchange,提问作者Peter Wilson
相关产品推荐
相关产品推荐

