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)
相关推荐
~Yogi1 小时前
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
学习·spring·缓存
七灵微1 小时前
【后端】单点登录
服务器·前端
Moonnnn.3 小时前
【单片机期末】单片机系统设计
笔记·单片机·嵌入式硬件·学习
行云流水剑5 小时前
【学习记录】使用 Kali Linux 与 Hashcat 进行 WiFi 安全分析:合法的安全测试指南
linux·学习·安全
持久的棒棒君5 小时前
npm安装electron下载太慢,导致报错
前端·electron·npm
crary,记忆7 小时前
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
前端·webpack·angular·angular.js
门前云梦7 小时前
《C语言·源初法典》---C语言基础(上)
c语言·开发语言·学习
漂流瓶jz7 小时前
让数据"流动"起来!Node.js实现流式渲染/流式传输与背后的HTTP原理
前端·javascript·node.js
SamHou08 小时前
手把手 CSS 盒子模型——从零开始的奶奶级 Web 开发教程2
前端·css·web
我不吃饼干8 小时前
从 Vue3 源码中了解你所不知道的 never
前端·typescript