MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下:

前言

Module Federation 的Webpack.config.js核心配置包括:

  1. name + filename(定义应用标识)

  2. remotes(引用远程模块)

  3. exposes(暴露本地模块)

  4. shared(共享依赖,优化加载)

Host应用中:

javascript 复制代码
// host/webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { ModuleFederationPlugin } = require('webpack').container;
const webpack = require('webpack');

module.exports = {
  // 📦 模式:development(开发)或 production(生产)
  mode: 'development',

  // 📂 构建入口:Webpack 构建从这里开始
  entry: './src/index.js',

  // 📤 构建输出
  output: {
    // 构建目录(dist 文件夹)
    path: path.resolve(__dirname, 'dist'),

    // 输出 JS 文件名(可以使用哈希做缓存)
    filename: '[name].[contenthash].js',

    // 所有静态资源的基础路径,必须指向 devServer 地址(用于加载 remote)
    publicPath: 'http://localhost:3000/',

    // 每次构建自动清空 dist 文件夹
    clean: true,
  },

  // 🌐 Dev Server 本地开发服务器配置
  devServer: {
    port: 3000, // 主机端口
    static: {
      directory: path.join(__dirname, 'dist'), // 静态资源路径
    },
    compress: true, // 启用 gzip 压缩
    hot: true, // 启用模块热替换
    historyApiFallback: true, // SPA 路由兼容
    open: true, // 启动时自动打开浏览器
    client: {
      overlay: true, // 编译错误以浮层形式显示
    },
  },

  // 📚 Source Map(方便调试)
  devtool: 'eval-source-map',

  // 📦 模块加载规则
  module: {
    rules: [
      {
        test: /\.js$/, // 匹配 JS 文件
        exclude: /node_modules/,
        use: 'babel-loader', // 使用 Babel 编译
      },
      {
        test: /\.css$/, // 匹配 CSS 文件
        use: ['style-loader', 'css-loader'], // 加载样式
      },
      {
        test: /\.(png|jpg|gif|svg)$/, // 图片加载
        type: 'asset/resource', // 转成文件资源
      },
    ],
  },

  // 🔧 模块解析配置
  resolve: {
    extensions: ['.js', '.jsx', '.json'], // 自动补全扩展名
    alias: {
      '@': path.resolve(__dirname, 'src'), // 设置路径别名
    },
    modules: [path.resolve(__dirname, 'src'), 'node_modules'], // 优先搜索路径
  },

  // 🎯 性能提示控制
  performance: {
    hints: false, // 不提示 bundle 过大
  },

  // ⚙️ 缓存配置
  cache: {
    type: 'filesystem', // 文件系统缓存(构建更快)
  },

  // 💡 Webpack 插件
  plugins: [
    // 自动生成 HTML 页面,并注入输出的 JS 脚本
    new HtmlWebpackPlugin({
      template: './public/index.html',
      favicon: './public/favicon.ico',
    }),

    // 允许定义全局变量(编译时替换)
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
    }),

    // 🌐 模块联邦核心插件
    new ModuleFederationPlugin({
      // 当前应用唯一标识
      name: 'host',

      // 使用远程模块的声明
      remotes: {
        remote1: 'remote1@http://localhost:3001/remoteEntry.js',
        remote2: 'remote2@http://localhost:3002/remoteEntry.js',
      },

      // 如果你要暴露本地组件(可选)
      exposes: {
        './LocalComponent': './src/components/LocalComponent.js',
      },

      // 共享模块(版本控制、避免重复加载)
      shared: {
        react: {
          // 必须的库名称
          requiredVersion: '^17.0.0',
          // 是否单例模式(防止重复加载)
          singleton: true,
          // 是否立即加载(false为异步)
          eager: true,
          // 允许的版本范围
          version: '17.0.2',
          // 严格版本检查
          strictVersion: false,
          // 共享作用域名称
          shareScope: 'default'
        }
      },
    }),
  ],

  // 🧠 优化配置(可选)
  optimization: {
    // 代码分割:把 node_modules 拆出来
    splitChunks: {
      chunks: 'all', // 所有模块分割
    },

    runtimeChunk: 'single', // 单独抽出运行时代码
    moduleIds: 'deterministic', // 稳定 moduleId,有利于长期缓存
  },

  // 🌍 目标环境(默认是 web)
  target: 'web',
};

Remote 应用的配置:

javascript 复制代码
new ModuleFederationPlugin({
  name: 'remote1',
  filename: 'remoteEntry.js', //定义远程入口文件的名称,默认值: remoteEntry.js
  library: { type: 'var', name: 'app1' },  //定义如何暴露模块
  exposes: {
    './Button': './src/components/Button.js',
  },
  shared: {
    lodash: {
      singleton: true,
      import: 'lodash', // 精确指定导入包名
      eager: true, // 提前加载,避免延迟加载风险
    },
    react: { singleton: true, requiredVersion: '^18.2.0' },
  },
});

跟host应用的稍微差别,主要体现在下面两个属性:

  • filename(字符串)

    • 定义远程入口文件的名称

    • 默认值: remoteEntry.js

    • 示例: filename:remoteEntry.js

    • 注意区分这个属性与下面表格中的output.filename,output.filename的全称是module.output.filename,但是这个属性的全称是module.filename

  • library (对象)

    • 定义如何暴露模块

    • 常用配置:

      javascript 复制代码
      library: {
        type: 'var',
        name: 'app1'
      }
    • type:暴露类型,可选值有var, module, assign, this, window, self, global, commonjs, commonjs2, amd, amd-require, umd, umd2, jsonp

    • name:暴露的全局变量名

总结表:

  • 常用属性总结:
模块 属性 含义
entry ./src/index.js 应用入口文件
output.path dist 构建输出目录
output.filename bundle.js 输出文件名
output.publicPath CDN 或本地路径 用于动态加载 remote
devServer.port 3000 本地开发端口
module.rules babel-loader, css-loader, asset 加载规则
plugins HtmlWebpackPlugin, ModuleFederationPlugin 插件系统
ModuleFederationPlugin.name 'host' 当前模块名
ModuleFederationPlugin.remotes 远程模块映射 remote 应用位置
ModuleFederationPlugin.exposes 本地暴露模块 可供 remote 使用
ModuleFederationPlugin.shared 共享模块 避免重复打包
optimization.splitChunks 公共依赖提取 减少重复代码
resolve.alias 路径别名 简化导入
cache.type 'filesystem' 启用构建缓存
performance.hints 'false' 忽略性能提示
  • 共享模块属性总结:
属性名 类型 说明
singleton boolean 是否只加载一份模块(如 React 必须 true
strictVersion boolean 是否强制匹配 requiredVersion,严格匹配版本
requiredVersion string 版本约束,所期望的依赖版本号(SemVer),要求的版本范围
version string 实际运行时模块的版本(建议提供)
eager boolean 是否在启动时立即加载,默认懒加载(默认 false,建议 false)
import `string false`
includeSecondaries boolean 是否包含子模块(如 react/jsx-runtime)
shareScope string 指定共享作用域(默认为 default)
相关推荐
关羽的小刀4 分钟前
Element-UI最新版暗藏Lodash漏洞?一次真实项目安全排查记录
前端
张志鹏PHP全栈4 分钟前
Vue3第五天,ref 和 reactive的介绍和区别
前端·vue.js
郭邯6 分钟前
import.meta对象是什么?
前端
sssammmm10 分钟前
AI入门学习-模型评估示例讲解
人工智能·学习
用泥种荷花22 分钟前
【NPM 笔记(一)】NPM 入门知识:命令、依赖与脚本核心
前端
大巨头23 分钟前
在vscode中使用通义灵码插件记录分享
前端
淮北49423 分钟前
STL学习(四、队列和堆栈)
开发语言·c++·学习
江城开朗的豌豆25 分钟前
Vue/React凭什么吊打传统前端?6年老司机带你揭秘它们的性能杀招!
前端·javascript·vue.js
江城开朗的豌豆26 分钟前
虚拟DOM:为什么React/Vue比直接操作DOM快10倍?
前端·javascript·vue.js
mrsk27 分钟前
JavaScript中的大数相加是怎么突破数字的极限的?
前端·javascript·面试