网上流传的一些 Webpack 5 资料里,偶尔会出现所谓 Code Universe 代码宇宙的说法,听起来很宏大,但如果你去翻 Webpack 官方的 Release Notes 和文档,会发现根本找不到这个名字的特性。实事求是的讲,这不是官方概念,更像是某些文章为了吸引眼球自造的包装词。不过换个角度看,Webpack 5 确实把整个应用的模块依赖关系构建成了一张庞大的图,从入口出发,经由 loader 转换、模块解析、依赖收集,最终产出优化后的产物,把这个过程形容成代码的宇宙倒也不算离谱。本文就以这个视角为线索,把 Webpack 5 真正值得关注的新特性逐个讲透。

模块联邦:让多个应用共享同一个代码宇宙
模块联邦(Module Federation)是 Webpack 5 里最重磅的新能力,它允许一个 JavaScript 应用在运行时动态加载另一个应用暴露出来的模块。也就是说,两个独立构建、独立部署的前端应用,可以在浏览器里互相借用代码。这在微前端架构出现之前几乎是不可能的事情,过去我们只能靠发 npm 包或者用 monorepo 把公共代码锁在构建期内,而模块联邦把共享时机推迟到了运行时。
它的配置由两部分组成:提供方使用 exposes 把内部模块暴露出去,消费方使用 remotes 声明远程来源。下面是一个最小可用的例子。
const { ModuleFederationPlugin } = require('webpack').container;
// 提供方应用 app-a 的配置
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'appA',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button.js'
},
shared: { react: { singleton: true } }
})
]
};
// 消费方应用 app-b 的配置
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'appB',
remotes: {
appA: 'appA@http://localhost:3000/remoteEntry.js'
},
shared: { react: { singleton: true } }
})
]
};消费方在代码里可以直接异步引入远程模块,写法和本地模块几乎没有差别,例如 const Button = React.lazy(() => import('appA/Button'))。配置里的 shared 选项尤其值得注意,它会让双方协商使用同一个版本的依赖,singleton: true 保证内存中只存在一份实例,这对 React 这类要求单例的库来说是必须的,否则会报非法 Hook 调用的错误。
当然模块联邦也不是银弹。远程模块的加载依赖网络,提供方发版后消费方拿到的是最新代码,缺乏版本锁定手段,一旦接口不兼容就会出现线上问题。所以实践中通常要配合版本协商策略和灰度发布来使用。
持久化缓存:二次构建速度的质变
Webpack 5 之前的缓存方案是放在内存里的 memory cache,进程一退出缓存就没了,CI 环境里基本享受不到增量构建的红利。Webpack 5 引入了基于文件系统的持久化缓存,配置非常简单。
module.exports = {
cache: {
type: 'filesystem',
buildDependencies: {
// 配置文件变化时让缓存失效
config: [__filename]
},
cacheDirectory: '.webpack_cache'
}
};它的原理是 Webpack 会把每个模块的解析结果、转换结果连同依赖关系一起序列化到磁盘。下次构建时先做一致性校验,只有发生变化的模块才会重新走 loader 流程,其余直接从缓存恢复。在大型项目里实测,二次冷启动的构建时间往往能缩短百分之六十到九十,项目越大收益越明显。
这里有一个容易踩的坑:buildDependencies 一定要把所有会影响构建行为的文件列进去,比如 babel 配置、postcss 配置。如果漏配了,改了配置但缓存没失效,就会出现构建结果和预期不一致的诡异问题,排查起来非常折磨人。另外 loader 如果自身有不可序列化的副作用,也可能破坏缓存的正确性,升级第三方 loader 时要留意其 Webpack 5 兼容性说明。
更聪明的 Tree Shaking 与新的资源模块
如果说前面两个特性是工程层面的升级,那 Tree Shaking 的增强就是产物体积层面的直接收益。Webpack 5 支持了对嵌套导出的摇树优化,也就是说 import { tool } from 'utils/kit' 时,如果 kit 内部又从别的模块 re-export 了内容,Webpack 现在能顺着依赖链把没用到的部分彻底剔除,而旧版本只能处理最外层。配合 sideEffects: false 的包声明,产物瘦身效果相当可观。
资源模块(Asset Modules)则是另一个实用的改进,它用四种内置类型替代了以前必须安装的 file-loader、url-loader 和 raw-loader。
module.exports = {
module: {
rules: [
{
test: /\.png$/,
type: 'asset', // 自动在 inline 和 resource 之间选择
parser: {
dataUrlCondition: { maxSize: 8 * 1024 }
}
},
{
test: /\.svg$/,
type: 'asset/source' // 导出源码字符串
}
]
}
};四种类型分别是 asset/resource 发出单独文件、asset/inline 转成 base64 内联、asset/source 导出源文本、asset 根据体积阈值自动二选一。少了几个 loader 依赖,配置更简洁,构建链路也更短。
除了这些,Webpack 5 还有长期缓存算法升级、不再为 Node.js 模块自动引入 polyfill、Top Level Await 支持等变化。其中 polyfill 的移除会让一些老包在浏览器端直接报错,需要在 resolve.fallback 里手动补齐,这是从 Webpack 4 迁移时最常见的问题。回到开头的问题,Code Universe 并非真实存在的特性,但它隐喻的模块依赖宇宙恰恰是理解 Webpack 的正确心智模型:你写的每一行代码,最终都被编织进这张图里,而 Webpack 5 的各项新能力,本质都是让这张图的构建更快、共享更灵活、产物更精简。
Webpack 5新特性Module Federation持久化缓存修改时间:2026-09-03 15:29:04