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

Webpack Module Federation能否共享整个组件目录?

如何通过Webpack Module Federation共享整个组件目录?

问题描述

我启动了一个新项目,希望复用现有项目中的组件。按照教程已成功共享JS、React文件以及图片等媒体资源,但不想在webpack.config.js中逐个声明组件,因此尝试直接共享整个组件目录。在exposes中配置如下代码:

exposes: {
        "./LeftNav": "./src/index.js",
        "./Button":  "./src/components/button/Button.jsx",
        "./MyComponentsLibrary":  "./src/components/"
      },

出现错误:

ERROR in container entry ./MyComponentsLibrary[0] Module not found: Error: Can't resolve './src/components/' in '[project_path]'

已检查路径拼写无误,想了解若可行该如何配置,若不可行有哪些替代方案?

完整webpack.config.js配置:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const getClientEnvironment = require('./env');
const webpack = require('webpack')

const dotenv = require('dotenv').config({ path: __dirname + '/.env' })
const dependencies = require("./package.json").dependencies;
const isDevelopment = process.env.NODE_ENV !== 'production'
const path = require("path");
const publicUrl = '';
const env = getClientEnvironment(publicUrl);

module.exports = {
  name: "left-nav",
  entry: "./src/index.js",
  mode: "development",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
  },
  devServer: {
    port: 3000,
    liveReload: true,
    historyApiFallback: true,
    headers: {
      'Cross-Origin-Embedder-Policy': 'unsafe-none'
    }
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        resolve: {
          extensions: ['.js', '.jsx']
        }        
      },
      {
        test: /\.(scss|css)$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
      {
        test: /\.(png|jpe?g|gif|svg|wav|ogg|mp3)$/i,
        use: [
          {
            loader: 'file-loader',
          },
        ],
      },
    ],
  },
  plugins: [   
    new webpack.DefinePlugin({
      'process.env': JSON.stringify(dotenv.parsed),
      'process.env.NODE_ENV': JSON.stringify(isDevelopment ? 'development' : 'production'),
    }),

    new HtmlWebpackPlugin({
      template: "./public/index.html",
      filename: "index.html",
    }),
    
    new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
    
    new MiniCssExtractPlugin(),

    new ModuleFederationPlugin({
      name: "leftNavigation",
      filename: "remoteEntry.js",
      remotes: {},
      exposes: {
        "./LeftNav": "./src/index.js",
        "./Button":  "./src/components/button/Button.jsx",
        "./MyComponentsLibrary":  "./src/components/"
      },
      shared: {
        "react": {
          singleton: true,
          eager: true,
          requiredVersion: dependencies.react
        },
        "react-dom": {
          singleton: true,
          requiredVersion: dependencies["react-dom"],
          eager: true 
        },
        "@mui/material": {
          singleton: true,
          requiredVersion: dependencies["@mui/material"],
          eager: true 
        },
        "@mui/icons-material": {
          singleton: true,
          requiredVersion: dependencies["@mui/icons-material"],
          eager: true 
        },
      }
    })
  ],
};

解决方案

Webpack Module Federation的exposes配置不支持直接暴露整个目录,它只能指向具体文件,无法识别目录路径,这是报错的核心原因。以下是三种可行的替代方案:

方案1:创建组件库入口文件(最推荐)

在src/components/目录下新建index.js(或index.jsx),统一导出所有需要共享的组件:

// src/components/index.js
export { default as Button } from './button/Button.jsx';
// 后续新增组件只需在此添加导出语句

修改exposes配置,指向这个入口文件:

exposes: {
  "./LeftNav": "./src/index.js",
  "./MyComponentsLibrary": "./src/components/index.js"
}

消费端可通过单一路径批量导入组件:

import { Button } from 'leftNavigation/MyComponentsLibrary';

方案2:使用自动暴露插件(进阶)

如果不想手动维护入口文件,可借助第三方插件自动扫描组件目录生成配置,比如webpack-module-federation-plugin-auto-exposes:

  1. 安装插件:
npm install webpack-module-federation-plugin-auto-exposes --save-dev
  1. 修改webpack配置,替换原ModuleFederationPlugin:
const { AutoModuleFederationPlugin } = require('webpack-module-federation-plugin-auto-exposes');

// 替换原有ModuleFederationPlugin配置
plugins: [
  // ...其他插件
  new AutoModuleFederationPlugin({
    name: "leftNavigation",
    filename: "remoteEntry.js",
    exposes: {
      './components': './src/components/**/*.jsx' // 配置组件扫描规则
    },
    shared: {
      // 保留原shared配置不变
      "react": { singleton: true, eager: true, requiredVersion: dependencies.react },
      "react-dom": { singleton: true, requiredVersion: dependencies["react-dom"], eager: true },
      "@mui/material": { singleton: true, requiredVersion: dependencies["@mui/material"], eager: true },
      "@mui/icons-material": { singleton: true, requiredVersion: dependencies["@mui/icons-material"], eager: true },
    }
  })
]

插件会自动扫描指定目录下的组件,无需手动维护导出配置。

方案3:逐个暴露组件(适合组件数量少的场景)

若组件数量不多,可继续保持逐个暴露的方式,配置直观但需手动添加新组件:

exposes: {
  "./LeftNav": "./src/index.js",
  "./Button": "./src/components/button/Button.jsx",
  // 新增组件时在此添加对应配置
}

消费端按需导入单个组件:

import Button from 'leftNavigation/Button';

针对当前配置的快捷修改建议

最简便的方式是采用方案1:

  1. 在src/components/下创建index.js并导出所有组件;
  2. 修改exposes中./MyComponentsLibrary的指向为./src/components/index.js,删除原指向目录的配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 22:14:59