You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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;

报错信息

错误截图


解决方案更新

已通过多引导模块的方式解决该问题:

  1. 为每个需要单独嵌入的Angular组件创建独立的模块与引导文件,在引导文件中封装组件的初始化和挂载逻辑(类似loadApp.ts的结构)
  2. 修改Angular的Module Federation配置,将这些引导文件作为暴露入口,而非直接暴露组件类
  3. 在React组件中,通过调用引导文件导出的挂载方法,将Angular组件渲染到指定的DOM容器中

内容的提问来源于stack exchange,提问作者Scerci

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 16:55:24