如何通过Module Federation在React中调用Angular非根组件?
在React应用中通过Module Federation嵌入Angular组件的问题
我希望通过Module Federation在React应用中嵌入Angular应用,目前已成功调用Angular的AppComponent,但无法调用其他组件。以下是相关配置代码:
Angular Webpack配置
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); const mf = require("@angular-architects/module-federation/webpack"); const path = require("path"); const share = mf.share; const sharedMappings = new mf.SharedMappings(); sharedMappings.register(path.join(__dirname, "tsconfig.json"), [ ]); module.exports = { output: { uniqueName: "mfeRemote", publicPath: "auto", scriptType: "text/javascript", }, optimization: { runtimeChunk: false, }, resolve: { alias: { ...sharedMappings.getAliases(), }, }, experiments: { outputModule: true, }, plugins: [ new ModuleFederationPlugin({ name: "mfeRemote", filename: "remoteEntry.js", exposes: { "./AppModule": "./src/loadApp.ts", "./DashComp": "./src/app/external/dashboard/dashboard.component.ts", }, shared: share({ "@angular/core": { singleton: true, strictVersion: true, requiredVersion: "auto", }, "@angular/common": { singleton: true, strictVersion: true, requiredVersion: "auto", }, "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: "auto", }, "@angular/router": { singleton: true, strictVersion: true, requiredVersion: "auto", }, ...sharedMappings.getDescriptors(), }), }), sharedMappings.getPlugin(), ], };
loadApp.ts
import 'zone.js'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; const mount = () => { platformBrowserDynamic() .bootstrapModule(AppModule) .catch((err) => console.error(err)); }; export { mount };
React Craco配置
const ModuleFederationPlugin = require("webpack").container.ModuleFederationPlugin; const deps = require("./package.json").dependencies; module.exports = { plugins: [ { plugin: { overrideCracoConfig: ({ cracoConfig, pluginOptions, context: { env, paths } }) => { return cracoConfig; }, overrideWebpackConfig: ({ webpackConfig, cracoConfig, pluginOptions, context: { env, paths } }) => { webpackConfig.plugins = [ ...webpackConfig.plugins, new ModuleFederationPlugin({ name: "app", remotes: { appModule: "mfeRemote@http://localhost:3002/remoteEntry.js", }, shared: { ...deps, "react-dom": { singleton: true, eager: true, }, react: { singleton: true, eager: true, }, }, }), ]; return webpackConfig; }, overrideDevServerConfig: ({ devServerConfig, cracoConfig, pluginOptions, context: { env, paths, proxy, allowedHost }, }) => { return devServerConfig; }, overrideJestConfig: ({ jestConfig, cracoConfig, pluginOptions, context: { env, paths, resolve, rootDir } }) => { return jestConfig; }, }, }, ], };
React调用根组件(可正常运行)
import React, { useEffect, useRef } from "react"; import { mount } from "appModule/AppModule"; const RemoteAppModule = () => { const ref = useRef(null); useEffect(() => { mount(); }, []); return ( <div className="remote-module"> <app-root></app-root> </div> ); }; export default RemoteAppModule;
React调用其他组件(运行失败)
import React from "react"; let DashComp = React.lazy(() => import("appModule/DashComp").then((module) => { // 尝试实例化组件类 let ExtModule = new module.DashboardComponent(); return { default: ExtModule }; }) ); const RemoteExtModule = () => { return ( <div> <React.Suspense fallback="...loading"> <DashComp /> </React.Suspense> </div> ); }; export default RemoteExtModule;
报错信息

解决方案更新
已通过多引导模块的方式解决该问题:
- 为每个需要单独嵌入的Angular组件创建独立的模块与引导文件,在引导文件中封装组件的初始化和挂载逻辑(类似
loadApp.ts的结构) - 修改Angular的Module Federation配置,将这些引导文件作为暴露入口,而非直接暴露组件类
- 在React组件中,通过调用引导文件导出的挂载方法,将Angular组件渲染到指定的DOM容器中
内容的提问来源于stack exchange,提问作者Scerci
相关产品推荐
相关产品推荐

