Webpack 5 联邦模块(Module Federation)详解

作者:望舒时间:2026-10-23 19:47:04浏览:589

本文深入解析 Webpack 5 的联邦模块特性,详细阐述其如何通过直接引用远程应用代码实现热插拔,从而替代传统的 npm 发包流程。文章提供了从配置 webpack.config.js 到在 React 中调用远程组件的完整代码示例,并探讨了基于联邦模块实现微前端架构的适用场景与技术限制。

联邦模块概述

本文主要介绍 Webpack 5 的新特性之一“联邦模块”(Module Federation),内容涵盖其核心特性、具体使用方法以及适用场景。

核心特性

特性

Webpack 5 引入联邦模式旨在更好地共享代码。在此之前,代码共享通常依赖 npm 发包,需经历构建、发布、引用三个阶段;而联邦模块允许直接引用其他应用的代码,实现热插拔效果,相比 npm 方式更加简洁、快速且方便。

使用方法

使用方法

  • 引入远程JS
  • Webpack配置
  • 模块使用

引入远程JS

引入远程JS

假设我们有两个应用 app1 和 app2,端口分别为 3001 和 3002。若 app1 需要引用 app2 中的 JS 文件,可以直接通过 script 标签引入。

例如,在 app1 应用的 index.html 中引入 app2 应用生成的 remoteEntry.js。


<head>
  <script src="http://localhost:3002/remoteEntry.js"></script>
 </head>

Webpack配置

Webpack配置

app1 的 webpack 配置如下:


const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
  
module.exports = {
 //....
 plugins: [
  new ModuleFederationPlugin({
   name: "app1",
   library: { type: "var", name: "app1" },
   remotes: {
    app2: "app2",
   },
   shared: ["react", "react-dom"],
  }),
 ],
};

对于 app2 的 webpack 配置如下:


plugins: [
  new ModuleFederationPlugin({
   name: "app2",
   library: { type: "var", name: "app2" },
   filename: "remoteEntry.js",
   exposes: {
    "./Button": "./src/Button",
   },
   shared: ["react", "react-dom"],
  })
 ],

可以看到,app1 和 app2 的配置基本相同,区别仅在于 app2 多出了 filename 和 exposes 属性。

配置参数详解

参数解释

  • name:应用名,需全局唯一,不可冲突。
  • library:UMD 标准导出,与 name 保持一致即可。
  • remotes:声明需要引用的远程应用。如上文 app1 配置中指定了需要引用的远程应用 app2。
  • filename:远程应用被其他应用引入时生成的 JS 文件名称,对应上述的 remoteEntry.js。
  • exposes:远程应用暴露出的模块名。
  • shared 依赖的包。
    • 若配置了此属性,Webpack 在加载时会先判断本地应用是否存在对应的包;如果不存在,则加载远程应用的依赖包。
    • 以 app2 为例,作为远程应用,它配置了 ["react", "react-dom"]。当被 app1 消费时,Webpack 会先查找 app1 是否存在这两个包,若不存在则使用 app2 自带的包。由于 app1 作为本地应用也声明了这两个参数,因此会直接使用 app1 本地的依赖。

模块使用

模块使用

对于 app1/App.js 代码中调用 app2 的组件,代码如下:


import React from "react";

const RemoteButton = React.lazy(() => import("app2/Button"));

const App = () => (
 <div>
  <h1>Basic Host-Remote</h1>
  <h2>App 1</h2>
  <React.Suspense fallback="Loading Button">
   <RemoteButton />
  </React.Suspense>
 </div>
);

export default App;

具体这一行


const RemoteButton = React.lazy(() => import("app2/Button")); 

使用方式为:import('远程应用名/暴露的模块名'),对应 webpack 配置中的 name 和 expose。其使用方式与引入普通异步组件无异。

适用范围与微前端

适用范围

由于 shared 属性的存在,本地应用和远程应用的技术栈及版本必须兼容,需统一使用同一套技术栈(如 JS 均使用 React,CSS 均使用 Sass 等)。

联邦模块与微前端的关系:由于 exposes 属性既可暴露单个组件,也可将整个应用暴露出去,且受 shared 属性限制技术栈必须一致,因此结合路由可实现类似 single-spa 模式的微前端架构。

使用场景:新建专门的组件应用服务来管理所有组件和应用,其他业务层只需根据业务需求载入对应的组件和功能模块即可。这种方式实现了模块的统一管理,代码质量高且搭建速度快,特别适用于矩阵应用或可视化页面搭建等场景。

联邦模块概述

例子的 github地址

到此这篇关于 Webpack 5 联邦模块介绍详解的文章就介绍到这了,更多相关 Webpack 5 联邦模块内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

作者最新文章