Webpack 5 Module Federation报错:无法解析远程模块'search/SearchAppModule'
尝试通过Webpack 5 Module Federation将运行在localhost:3001的Angular远程应用模块共享给React宿主应用时,React端出现Module not found: Error: Can't resolve 'search/SearchAppModule'错误,以下是针对性的修复方案:
1. 调整React宿主的ModuleFederationPlugin配置顺序
Create React App默认会注入HtmlWebpackPlugin,如果ModuleFederationPlugin放在它之后,远程模块的remoteEntry.js不会被自动注入到HTML中,导致Webpack无法解析远程模块。需要在craco配置中将ModuleFederationPlugin插入到HtmlWebpackPlugin之前:
修改craco.config.js:
const { ModuleFederationPlugin } = require("webpack").container; const HtmlWebpackPlugin = require('html-webpack-plugin'); const deps = require("./package.json").dependencies; module.exports = { plugins: [ { plugin: { overrideWebpackConfig: ({ webpackConfig }) => { // 找到HtmlWebpackPlugin的位置 const htmlPluginIndex = webpackConfig.plugins.findIndex( plugin => plugin instanceof HtmlWebpackPlugin ); // 在HtmlWebpackPlugin之前插入ModuleFederationPlugin webpackConfig.plugins.splice(htmlPluginIndex, 0, new ModuleFederationPlugin({ name: "app", remotes: { search: "search@http://localhost:3001/remoteEntry.js", }, shared: { ...deps, "react-dom": { singleton: true, eager: true }, react: { singleton: true, eager: true }, }, })); return webpackConfig; }, overrideCracoConfig: ({ cracoConfig }) => cracoConfig, overrideDevServerConfig: ({ devServerConfig }) => devServerConfig, overrideJestConfig: ({ jestConfig }) => jestConfig, }, }, ], };
2. 确保Angular远程应用的loadApp.ts正确导出mount函数
远程应用的exposes指向src/loadApp.ts,需要该文件导出一个能接收DOM节点的mount方法,用于在React中挂载Angular应用:
创建/修改src/loadApp.ts:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { ApplicationRef } from '@angular/core'; import { AppModule } from './app/app.module'; import { AppComponent } from './app/app.component'; export function mount(element: HTMLElement) { platformBrowserDynamic().bootstrapModule(AppModule, { ngZoneEventCoalescing: true }).then(moduleRef => { // 将Angular应用挂载到指定DOM节点 const appRef = moduleRef.injector.get(ApplicationRef); const componentRef = appRef.bootstrap(AppComponent); element.appendChild(componentRef.location.nativeElement); }).catch(err => console.error(err)); }
3. 修正React组件中mount函数的调用逻辑
React的SearchAppModule.js中,mount()没有传递挂载的DOM节点,且建议使用动态导入确保远程模块在运行时加载:
修改src/modules/SearchAppModule.js:
import React, { useEffect, useRef } from "react"; const SearchAppModule = () => { const ref = useRef(null); useEffect(() => { let cleanup; // 动态导入远程模块,避免编译时解析错误 import('search/SearchAppModule').then(module => { if (ref.current) { module.mount(ref.current); // 可选:添加卸载逻辑(如果Angular端实现了unmount方法) // cleanup = module.unmount; } }); return () => { if (cleanup) cleanup(); }; }, []); return <div className="search-app-module" ref={ref} />; }; export default SearchAppModule;
4. 修复Angular依赖版本不兼容问题
当前Angular版本为16,但@angular-architects/module-federation版本为14.3.0-beta.3,版本不匹配会导致模块导出异常。升级该依赖到Angular 16对应的版本:
修改Angular远程应用的package.json:
{ "dependencies": { "@angular-architects/module-federation": "^16.0.0" } }
执行npm install更新依赖后重新启动远程应用。
内容的提问来源于stack exchange,提问作者Vid Potočnik

