How to integrate React Craco app into webpack module federation

207 阅读2分钟

Remote app configurations


const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const path = require("path");
const WebpackBar = require("webpackbar");
const deps = require("./package.json").dependencies;
process.env.port = 8085;  //指定端口号
module.exports = {
  webpack: {
    plugins: {
      add: [
        new ModuleFederationPlugin({
          name: "microFrontEnd5",
          filename: "remoteEntry.js",
          exposes: [  //定义需要导出的组件
            {
              "./MicroFrontEnd5Index": "./src/index",
            },
            {
              "./NotFound": "./src/pages/form/basicForm/index.tsx",
            },
           // "./public-path",
          ],
          shared: {
            ...deps,
            react: {
              eager: true, //需要配置,否则会报多实例错误
              singleton: true,
              requiredVersion: deps.react,
            },
            "react-dom": {
              eager: true,
              singleton: true,
              requiredVersion: deps["react-dom"],
            },
          },
        }),
        new HtmlWebpackPlugin({
          template: "./public/index.html",
        }),
        new WebpackBar({
          color: "#85d", // 默认green,进度条颜色支持HEX
          basic: false, // 默认true,启用一个简单的日志报告器
          profile: false, // 默认false,启用探查器。
        }),
      ],
    },
    entry: {
     // microFrontEnd5: "./public-path",  //动态修改public_path
    },
    configure: (webpackConfig, { env, paths }) => {
      paths.appBuild = "dist";
      webpackConfig.output = {
        ...webpackConfig.output,
        path: path.resolve(__dirname, "dist"), // 修改输出文件目录
        publicPath: "auto",
      };
      console.log(webpackConfig);
      return webpackConfig;
    },
  },
};
添加ModuleFederationPlugin插件
通过Craco提供的webpack plugins add属性添加,ModuleFederationPlugin中的expose代表需要导出的组件,可以是整个应用也可以是组件。shared是需要共享的实例
````
 module.exports = {
  webpack: {
    plugins: {
      add: [
        new ModuleFederationPlugin({
          name: "microFrontEnd5",
          filename: "remoteEntry.js",
          exposes: [  //定义需要导出的组件
            {
              "./MicroFrontEnd5Index": "./src/index",
            },
            {
              "./NotFound": "./src/pages/form/basicForm/index.tsx",
            },
           // "./public-path",
          ],
          shared: {
            ...deps,
            react: {
              eager: true, //需要配置,否则会报多实例错误
              singleton: true,
              requiredVersion: deps.react,
            },
            "react-dom": {
              eager: true,
              singleton: true,
              requiredVersion: deps["react-dom"],
            },
          },
        }),
        new WebpackBar({
          color: "#85d", // 默认green,进度条颜色支持HEX
          basic: false, // 默认true,启用一个简单的日志报告器
          profile: false, // 默认false,启用探查器。
        }),
      ],
    },
  },
};
````

配置webpack output的public_path

paublic_path 是container加载子应用的基础路径,设置auto子应用才会加载正确的路径。
````
webpack:{
    ...,
  configure: (webpackConfig, { env, paths }) => {
  paths.appBuild = "dist";
  webpackConfig.output = {
    ...webpackConfig.output,
    path: path.resolve(__dirname, "dist"), // 修改输出文件目录
    publicPath: "auto", 
  };
  console.log(webpackConfig);
  return webpackConfig;
 },
 }
````
修改子应用名称

index.html中修改id,以及对应的React app渲染dom

    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="ai"></div>
    
    const root = ReactDOM.createRoot(
    document.getElementById("aiChatbotApp") as HTMLElement
    );
    root.render(
        <App></App>
    );

container配置

    webpack:{
        plugins: [
        new ModuleFederationPlugin({
          name: "container",
          filename: "remoteEntry.js",
          remotes: {
            microFrontEnd1: "microFrontEnd1@http://localhost:8081/remoteEntry.js",
            microFrontEnd2: "microFrontEnd2@http://localhost:8082/remoteEntry.js",
            microFrontEnd3: "microFrontEnd3@http://localhost:8083/remoteEntry.js",
            microFrontEnd4: "microFrontEnd4@http://localhost:8084/remoteEntry.js",
            microFrontEnd5: "microFrontEnd5@http://localhost:8085/remoteEntry.js",
            aiChatbot: "aiChatbot@http://localhost:3001/ai-chatbot/remoteEntry.js", //如果子应用有baseHref 配置在这
          }
        })
      ],
    }

在host使用remote应用

import "aiChatbot/AiChatbotApp"; //aiChatbot是应用名称,AiChatbotApp是expose的组件