Webpack 5 发布已经有相当长一段时间,但不少团队的项目仍然停留在 Webpack 4,一方面是担心升级带来的破坏性变更,另一方面是对新特性缺乏系统了解。其实 Webpack 5 带来的不只是常规的性能优化,其中 Module Federation(模块联邦)几乎重新定义了多个应用之间共享代码的方式,配合持久化缓存等特性,构建体验有了质的提升。本文将从实际项目角度出发,把这些特性拆开讲清楚。

Module Federation:运行时共享模块的核心机制
模块联邦要解决的问题是:两个独立构建、独立部署的应用,如何在运行时互相引用对方的模块。在传统方案里,跨项目复用代码只有两条路,要么抽成 npm 包发布再各自安装,要么走微前端的运行时加载。前者意味着每次改动都要发版、升版本、重新构建所有下游项目,后者又常常引入额外的框架和复杂的通信协议。模块联邦提供了第三条路:把某个模块直接暴露出去,其他应用通过网络在运行时加载它。
它的配置由两个角色组成:提供模块的一方叫远程应用,通过 exposes 把内部模块暴露出去;消费模块的一方叫宿主应用,通过 remotes 声明远程地址,代码里就可以像本地模块一样 import。下面是一个最小可用的配置示例:
// 远程应用 webpack.config.js
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: "remoteApp",
filename: "remoteEntry.js",
exposes: {
"./Button": "./src/components/Button.js"
},
shared: { react: { singleton: true }, "react-dom": { singleton: true } }
})
]
};
// 宿主应用 webpack.config.js
new ModuleFederationPlugin({
name: "hostApp",
remotes: {
remoteApp: "remoteApp@http://cdn.ipipp.com/remoteEntry.js"
},
shared: { react: { singleton: true }, "react-dom": { singleton: true } }
});
// 宿主业务代码中直接使用
import Button from "remoteApp/Button";
这里的关键点是 shared 配置。宿主和远程共享依赖时,Webpack 会在运行时协商版本,只要版本范围兼容就只加载一份 React,避免出现多个框架实例导致的报错。singleton: true 则强制全局唯一,这是使用 React 这类有全局状态依赖的库时几乎必开的选项。另外要注意,宿主在首次渲染时远程模块还没加载完成,需要配合 React.lazy 和 Suspense 做异步加载,否则会直接抛出加载错误。
持久化缓存:二次构建快到可以忽略
Webpack 5 移除了 Webpack 4 时代的 cache-loader 和 happypack 这类第三方缓存方案,把文件系统缓存做进了内核。开启方式非常简单:
module.exports = {
cache: {
type: "filesystem",
buildDependencies: {
// 配置文件本身变化时让缓存失效
config: [__filename]
}
}
};
开启后,Webpack 会把每个模块的处理结果序列化到 node_modules/.cache/webpack 目录,二次构建时只重新处理发生变化的文件。在中大型项目里,冷启动构建可能需要一两分钟,而命中缓存的增量构建往往能压缩到几秒。缓存失效的粒度也比 Webpack 4 精细得多,loader 版本、依赖版本、配置内容任何一个因素变化都会触发对应模块的重新编译,不会出现改了 babel 配置但缓存没刷新导致线上异常这种隐蔽问题。
有一个实践建议值得强调:在 CI 环境中可以把缓存目录作为产物持久化,下次流水线构建直接复用,整条流水线的耗时能明显下降。同时要注意 buildDependencies 一定要把 webpack 配置文件、babel 配置文件列进去,否则修改构建配置后旧缓存仍然生效,排查起来非常浪费时间。
其他值得关注的改进与升级注意事项
除了上面两个大头,Webpack 5 还有几个经常被用到的改进。第一是资源模块(Asset Modules),asset/resource、asset/inline 等类型替代了 file-loader 和 url-loader,图片、字体这类资源的处理不再需要额外安装 loader。第二是 Tree Shaking 能力增强,支持了嵌套的无用导出消除和公共代码拆分更精细的 splitChunks 策略,对产物体积的削减是实打实的。第三是长期废弃的 Node.js polyfill 不再默认注入,浏览器端包体积变小了,但一些老依赖引用了 process、path 等全局变量时需要手动安装并声明 resolve.fallback。
升级过程中最常见的问题集中在三点:一是 Node.js 版本必须大于等于 10.13,建议直接用 14 以上的 LTS 版本;二是部分老 loader 和插件不兼容,尤其是一些深度操作 AST 的 babel 插件需要同步升级;三是 splitChunks 默认行为有调整,拆包结果变化后要重新核对首屏加载的资源清单。建议升级前先跑一遍构建产物分析,升级后逐一对比 chunk 数量和体积,做到心中有数。
总体来看,如果你的项目存在多应用共享业务组件的需求,模块联邦值得认真评估;如果只是单体应用,持久化缓存加上更激进的 Tree Shaking 也足以构成升级理由。升级前做好依赖版本排查和产物对比,风险是完全可控的。
Webpack 5Module Federation前端工程化修改时间:2026-09-06 09:30:32