如何在 React 微前端中使用多个模块之间的公共依赖关系

发布于 2025-01-18 03:53:13 字数 8437 浏览 2 评论 0原文

嘿,我正在使用WebPack模块联合会中的React项目中使用React Microfrontend。 根据微电重元结构更改文件夹结构后,面临一些困难来处理模块的共同依赖性。

获取以下错误:

    ERROR in resolving fallback for shared module react
    Module not found: Error: Can't resolve 'react' in '/Users/admin/Desktop/guru/project/microfrontend/modules/metronic/layout/components/subheader/components'
    ERROR in resolving fallback for shared module react
Module not found: Error: Can't resolve 'react-router-dom' in '/Users/admin/Desktop/guru/project/microfrontend/modules/metronic/layout/components/subheader/components'

在这里我共享我的代码结构

  1. webpack
  2. 软件包。json
  3. 文件夹结构

webpack:

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
require('dotenv').config({ path: '../.env' });

module.exports = {
  // the output bundle won't be optimized for production but suitable for development
  mode: 'development',
  // the app entry point is /src/index.js
  entry: path.resolve(__dirname, 'src', 'index.js'),
  output: {
    // the output of the webpack build will be in /dist directory
    path: path.resolve(__dirname, 'dist'),
    // the filename of the JS bundle will be bundle.js
    filename: 'bundle.js',
    publicPath: '/'
  },
  devServer: {
    historyApiFallback: true,
  },
  resolve: {
    extensions: ['', '.js', '.jsx'],
  },
  module: {
    rules: [
      {
        // for any file with a suffix of js or jsx
        test: /\.jsx?$/,
        // ignore transpiling JavaScript from node_modules as it should be that state
        exclude: /node_modules/,
        // use the babel-loader for transpiling JavaScript to a suitable format
        loader: 'babel-loader',
        options: {
          // attach the presets to the loader (most projects use .babelrc file instead)
          presets: ["@babel/preset-env", "@babel/preset-react"]
        }
      },
      {
        // test: /\.s[ac]ss$/i,
        test: /\.(sa|sc|c)ss$/,
        use: [
          // Creates `style` nodes from JS strings
          "style-loader",
          // Translates CSS into CommonJS
          "css-loader",
          // Compiles Sass to CSS
          "sass-loader",
        ],
      },
      {
        test: /\.(woff(2)?|ttf|eot|svg|png)(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
              outputPath: 'fonts/'
            }
          }
        ]
      }
    ]
  },
  // add a custom index.html as the template
  plugins: [
    new ModuleFederationPlugin({
        name: "app_container",
        remotes: {
            banners: "banners@http://localhost:3002/remoteEntry.js",
            newDashboard: "newDashboard@http://localhost:3008/remoteEntry.js",
            baggageService: "baggageService@http://localhost:3016/remoteEntry.js",

        },
        // shared: [ "react", "react-dom"]
        shared: {
          "react-router-dom": { singleton: true, eager: true, requiredVersion: "^5.1.2" },
          "@manaflair/redux-batch":{ singleton: true, eager: true, requiredVersion: "1.0.0" },
          "@reduxjs/toolkit":{ singleton: true, eager: true, requiredVersion: "1.3.6" },
          "react-redux":{ singleton: true, eager: true, requiredVersion: "7.1.3" },
          "redux":{ singleton: true, eager: true, requiredVersion: "4.0.5" },
          "redux-logger":{ singleton: true, eager: true, requiredVersion: "^3.0.6" },
          "redux-persist":{ singleton: true, eager: true, requiredVersion: "6.0.0" },
          "redux-saga":{ singleton: true, eager: true, requiredVersion: "1.1.3" },
          "react": { singleton: true, eager: true, requiredVersion: "^17.0.2" },
          "@fortawesome/fontawesome-free": { singleton: true, eager: true, requiredVersion: "5.13.0" },
          "react-dom": { singleton: true, eager: true, requiredVersion: "^17.0.2" },
          "lodash": { singleton: true, eager: true, requiredVersion: "4.17.21" },
          "lodash.debounce": { singleton: true, eager: true, requiredVersion: "^4.0.8" },
        }
    }),
    new HtmlWebpackPlugin({
        template: "./public/index.html"
    }),
    new webpack.DefinePlugin({
      "process.env": JSON.stringify(process.env)
    })
  ]
};

在我们的项目中,有常见的util和组件,这些组件在不同的微型前端模块中使用 如何处理这些依赖性。

package.json:

{
  "name": "microfrontend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --open",
    "build": "webpack --config webpack.prod.config.js --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  },
  "devDependencies": {
    "@amcharts/amcharts3-react": "^3.0.0",
    "@babel/core": "^7.17.5",
    "@babel/preset-env": "^7.16.11",
    "@babel/preset-react": "^7.16.7",
    "@date-io/date-fns": "^1.3.11",
    "@formatjs/intl-pluralrules": "1.3.5",
    "@fortawesome/fontawesome-free": "^5.13.0",
    "@manaflair/redux-batch": "1.0.0",
    "@material-ui/core": "^4.10.2",
    "@material-ui/icons": "4.9.1",
    "@material-ui/pickers": "^3.3.10",
    "@material-ui/styles": "4.9.14",
    "@reduxjs/toolkit": "1.3.6",
    "@tanem/svg-injector": "8.0.50",
    "@wojtekmaj/react-daterange-picker": "^3.3.0",
    "apexcharts": "3.24.0",
    "axios": "0.21.2",
    "axios-mock-adapter": "1.18.1",
    "babel-loader": "^8.2.3",
    "bootstrap": "4.5.0",
    "bootstrap-daterangepicker": "^3.1.0",
    "clipboard-copy": "3.1.0",
    "clsx": "1.1.0",
    "cp-cli": "2.0.0",
    "css-mediaquery": "0.1.2",
    "date-fns": "2.8.1",
    "downshift": "3.4.2",
    "fg-loadcss": "2.1.0",
    "file-loader": "^6.2.0",
    "formik": "2.1.4",
    "highcharts": "^9.0.0",
    "highcharts-react-official": "^3.0.0",
    "html-react-parser": "^0.13.0",
    "html-webpack-plugin": "^5.5.0",
    "html2canvas": "^1.3.2",
    "http-service": "file:../modules/http-service",
    "i": "^0.3.7",
    "json2mq": "0.2.0",
    "jss-rtl": "^0.3.0",
    "lodash": "4.17.21",
    "lodash.debounce": "^4.0.8",
    "material-picker-4.0": "npm:@material-ui/pickers@^4.0.0-alpha.12",
    "material-ui-popup-state": "1.4.1",
    "metronic": "file:../modules/metronic",
    "npm": "^6.14.6",
    "object-path": "0.11.8",
    "perfect-scrollbar": "1.5.0",
    "prop-types": "15.7.2",
    "quill-emoji": "^0.1.7",
    "react-beautiful-dnd": "^13.1.0",
    "react-bootstrap": "1.0.1",
    "react-bootstrap-daterangepicker": "^7.0.0",
    "react-bootstrap-table-next": "4.0.2",
    "react-bootstrap-table2-paginator": "2.1.2",
    "react-copy-to-clipboard": "^5.0.2",
    "react-data-table-component": "^6.9.3",
    "react-datepicker": "2.16.0",
    "react-draggable": "4.4.2",
    "react-highcharts": "^16.1.0",
    "react-hooks-helper": "^1.6.0",
    "react-html-parser": "^2.0.2",
    "react-image-crop": "^8.6.12",
    "react-inlinesvg": "1.2.0",
    "react-intl": "3.6.2",
    "react-is": "16.13.1",
    "react-pdf": "^5.7.0",
    "react-perfect-scrollbar": "1.5.8",
    "react-portal": "4.2.0",
    "react-qr-reader": "^2.2.1",
    "react-quill": "^1.3.5",
    "react-redux": "7.1.3",
    "react-router-dom": "5.1.2",
    "react-router-last-location": "^2.0.1",
    "react-rte": "^0.16.1",
    "react-scripts": "3.2.0",
    "react-select": "3.1.0",
    "react-star-ratings": "^2.3.0",
    "react-swipeable-views": "0.13.9",
    "react-syntax-highlighter": "12.2.1",
    "react-table-hoc-fixed-columns": "^2.3.4",
    "react-toastify": "^6.0.6",
    "react-window": "1.8.5",
    "reactstrap": "^8.5.1",
    "redux": "4.0.5",
    "redux-logger": "^3.0.6",
    "redux-persist": "6.0.0",
    "redux-saga": "1.1.3",
    "sass": "^1.49.9",
    "sass-loader": "^12.6.0",
    "socicon": "3.0.5",
    "styled-components": "^5.1.1",
    "sweetalert2": "^10.12.6",
    "sweetalert2-react-content": "^3.2.2",
    "common-gui-components": "file:../modules/common-gui-components",
    "common-store": "file:../modules/common-store",
    "common-utils": "file:../modules/common-utils",
    "uuid": "^8.3.2",
    "webpack": "^5.70.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.7.4",
    "yup": "0.29.0"
  }
}

我的文件夹结构:

“在此处输入映像说明”

Hey I am using react microfrontend in my react project with webpack module federation.
After changing folder structure as per microfrontend structure facing some difficulties to handle common dependencies of modules.

Getting Following Error:

    ERROR in resolving fallback for shared module react
    Module not found: Error: Can't resolve 'react' in '/Users/admin/Desktop/guru/project/microfrontend/modules/metronic/layout/components/subheader/components'
    ERROR in resolving fallback for shared module react
Module not found: Error: Can't resolve 'react-router-dom' in '/Users/admin/Desktop/guru/project/microfrontend/modules/metronic/layout/components/subheader/components'

Here I am sharing my code structure

  1. webpack
  2. package.json
  3. folder structure

Webpack:

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
require('dotenv').config({ path: '../.env' });

module.exports = {
  // the output bundle won't be optimized for production but suitable for development
  mode: 'development',
  // the app entry point is /src/index.js
  entry: path.resolve(__dirname, 'src', 'index.js'),
  output: {
    // the output of the webpack build will be in /dist directory
    path: path.resolve(__dirname, 'dist'),
    // the filename of the JS bundle will be bundle.js
    filename: 'bundle.js',
    publicPath: '/'
  },
  devServer: {
    historyApiFallback: true,
  },
  resolve: {
    extensions: ['', '.js', '.jsx'],
  },
  module: {
    rules: [
      {
        // for any file with a suffix of js or jsx
        test: /\.jsx?$/,
        // ignore transpiling JavaScript from node_modules as it should be that state
        exclude: /node_modules/,
        // use the babel-loader for transpiling JavaScript to a suitable format
        loader: 'babel-loader',
        options: {
          // attach the presets to the loader (most projects use .babelrc file instead)
          presets: ["@babel/preset-env", "@babel/preset-react"]
        }
      },
      {
        // test: /\.s[ac]ss$/i,
        test: /\.(sa|sc|c)ss$/,
        use: [
          // Creates `style` nodes from JS strings
          "style-loader",
          // Translates CSS into CommonJS
          "css-loader",
          // Compiles Sass to CSS
          "sass-loader",
        ],
      },
      {
        test: /\.(woff(2)?|ttf|eot|svg|png)(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
              outputPath: 'fonts/'
            }
          }
        ]
      }
    ]
  },
  // add a custom index.html as the template
  plugins: [
    new ModuleFederationPlugin({
        name: "app_container",
        remotes: {
            banners: "banners@http://localhost:3002/remoteEntry.js",
            newDashboard: "newDashboard@http://localhost:3008/remoteEntry.js",
            baggageService: "baggageService@http://localhost:3016/remoteEntry.js",

        },
        // shared: [ "react", "react-dom"]
        shared: {
          "react-router-dom": { singleton: true, eager: true, requiredVersion: "^5.1.2" },
          "@manaflair/redux-batch":{ singleton: true, eager: true, requiredVersion: "1.0.0" },
          "@reduxjs/toolkit":{ singleton: true, eager: true, requiredVersion: "1.3.6" },
          "react-redux":{ singleton: true, eager: true, requiredVersion: "7.1.3" },
          "redux":{ singleton: true, eager: true, requiredVersion: "4.0.5" },
          "redux-logger":{ singleton: true, eager: true, requiredVersion: "^3.0.6" },
          "redux-persist":{ singleton: true, eager: true, requiredVersion: "6.0.0" },
          "redux-saga":{ singleton: true, eager: true, requiredVersion: "1.1.3" },
          "react": { singleton: true, eager: true, requiredVersion: "^17.0.2" },
          "@fortawesome/fontawesome-free": { singleton: true, eager: true, requiredVersion: "5.13.0" },
          "react-dom": { singleton: true, eager: true, requiredVersion: "^17.0.2" },
          "lodash": { singleton: true, eager: true, requiredVersion: "4.17.21" },
          "lodash.debounce": { singleton: true, eager: true, requiredVersion: "^4.0.8" },
        }
    }),
    new HtmlWebpackPlugin({
        template: "./public/index.html"
    }),
    new webpack.DefinePlugin({
      "process.env": JSON.stringify(process.env)
    })
  ]
};

In our project have common utils and components that is being used in different micro frontend modules
how to handle that dependencies.

package.json:

{
  "name": "microfrontend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --open",
    "build": "webpack --config webpack.prod.config.js --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  },
  "devDependencies": {
    "@amcharts/amcharts3-react": "^3.0.0",
    "@babel/core": "^7.17.5",
    "@babel/preset-env": "^7.16.11",
    "@babel/preset-react": "^7.16.7",
    "@date-io/date-fns": "^1.3.11",
    "@formatjs/intl-pluralrules": "1.3.5",
    "@fortawesome/fontawesome-free": "^5.13.0",
    "@manaflair/redux-batch": "1.0.0",
    "@material-ui/core": "^4.10.2",
    "@material-ui/icons": "4.9.1",
    "@material-ui/pickers": "^3.3.10",
    "@material-ui/styles": "4.9.14",
    "@reduxjs/toolkit": "1.3.6",
    "@tanem/svg-injector": "8.0.50",
    "@wojtekmaj/react-daterange-picker": "^3.3.0",
    "apexcharts": "3.24.0",
    "axios": "0.21.2",
    "axios-mock-adapter": "1.18.1",
    "babel-loader": "^8.2.3",
    "bootstrap": "4.5.0",
    "bootstrap-daterangepicker": "^3.1.0",
    "clipboard-copy": "3.1.0",
    "clsx": "1.1.0",
    "cp-cli": "2.0.0",
    "css-mediaquery": "0.1.2",
    "date-fns": "2.8.1",
    "downshift": "3.4.2",
    "fg-loadcss": "2.1.0",
    "file-loader": "^6.2.0",
    "formik": "2.1.4",
    "highcharts": "^9.0.0",
    "highcharts-react-official": "^3.0.0",
    "html-react-parser": "^0.13.0",
    "html-webpack-plugin": "^5.5.0",
    "html2canvas": "^1.3.2",
    "http-service": "file:../modules/http-service",
    "i": "^0.3.7",
    "json2mq": "0.2.0",
    "jss-rtl": "^0.3.0",
    "lodash": "4.17.21",
    "lodash.debounce": "^4.0.8",
    "material-picker-4.0": "npm:@material-ui/pickers@^4.0.0-alpha.12",
    "material-ui-popup-state": "1.4.1",
    "metronic": "file:../modules/metronic",
    "npm": "^6.14.6",
    "object-path": "0.11.8",
    "perfect-scrollbar": "1.5.0",
    "prop-types": "15.7.2",
    "quill-emoji": "^0.1.7",
    "react-beautiful-dnd": "^13.1.0",
    "react-bootstrap": "1.0.1",
    "react-bootstrap-daterangepicker": "^7.0.0",
    "react-bootstrap-table-next": "4.0.2",
    "react-bootstrap-table2-paginator": "2.1.2",
    "react-copy-to-clipboard": "^5.0.2",
    "react-data-table-component": "^6.9.3",
    "react-datepicker": "2.16.0",
    "react-draggable": "4.4.2",
    "react-highcharts": "^16.1.0",
    "react-hooks-helper": "^1.6.0",
    "react-html-parser": "^2.0.2",
    "react-image-crop": "^8.6.12",
    "react-inlinesvg": "1.2.0",
    "react-intl": "3.6.2",
    "react-is": "16.13.1",
    "react-pdf": "^5.7.0",
    "react-perfect-scrollbar": "1.5.8",
    "react-portal": "4.2.0",
    "react-qr-reader": "^2.2.1",
    "react-quill": "^1.3.5",
    "react-redux": "7.1.3",
    "react-router-dom": "5.1.2",
    "react-router-last-location": "^2.0.1",
    "react-rte": "^0.16.1",
    "react-scripts": "3.2.0",
    "react-select": "3.1.0",
    "react-star-ratings": "^2.3.0",
    "react-swipeable-views": "0.13.9",
    "react-syntax-highlighter": "12.2.1",
    "react-table-hoc-fixed-columns": "^2.3.4",
    "react-toastify": "^6.0.6",
    "react-window": "1.8.5",
    "reactstrap": "^8.5.1",
    "redux": "4.0.5",
    "redux-logger": "^3.0.6",
    "redux-persist": "6.0.0",
    "redux-saga": "1.1.3",
    "sass": "^1.49.9",
    "sass-loader": "^12.6.0",
    "socicon": "3.0.5",
    "styled-components": "^5.1.1",
    "sweetalert2": "^10.12.6",
    "sweetalert2-react-content": "^3.2.2",
    "common-gui-components": "file:../modules/common-gui-components",
    "common-store": "file:../modules/common-store",
    "common-utils": "file:../modules/common-utils",
    "uuid": "^8.3.2",
    "webpack": "^5.70.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.7.4",
    "yup": "0.29.0"
  }
}

My folder structure:

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文