Abandoning Universe 这个叫法并不是 Webpack 官方文档里的正式特性,而是社区对 Webpack 5 中更彻底移除未使用代码行为的一种形象概括。它的底层仍然是 tree shaking,但 Webpack 5 把这一能力扩展到了模块级别:不仅擦除未引用的导出,还能在确认模块无副作用的前提下,把整个模块乃至整条依赖链从产物中剔除。换句话说,只要条件允许,Webpack 5 会毫不犹豫地放弃一整片“宇宙”,而不是只摘掉几颗没用的星星。这个能力的关键在于对模块依赖图的精确标记,以及 sideEffects 字段的广泛支持。

传统 tree shaking 依赖于 ES Module 的静态结构分析。如果一个模块导出了多个函数,但业务代码只使用了其中一个,Webpack 可以把未使用的导出从最终 bundle 中删除。然而问题在于,模块本身可能仍然会被保留,因为打包器无法判断该模块是否含有隐式副作用。比如一个模块在顶层执行了 console.log 或修改了全局变量,即使它的导出没有被使用,直接删除整个模块也可能改变程序行为。Webpack 5 的改进之处在于,它让开发者能够通过 sideEffects 字段主动声明“我的模块没有副作用,可以安全删除”,从而把 tree shaking 从导出级别提升到模块级别。
从 Tree Shaking 到 Abandoning Universe:核心变化在哪里
要理解“放弃宇宙”的威力,先得看清传统 tree shaking 的局限。假设项目里引入了 lodash 这样的工具库,传统做法是 import { debounce } from 'lodash'。在旧版 Webpack 中,如果 lodash 没有提供 ES Module 版本,整个 lodash 文件会被打入 bundle,体积瞬间膨胀几十 KB。即使 lodash-es 提供了 ESM 格式,Webpack 也只能移除未导入的函数导出,但 lodash-es 内部的很多模块仍然会被保留,因为它们存在潜在的副作用。
Webpack 5 通过更细粒度的模块依赖图分析,配合 package.json 中的 sideEffects: false,可以做到只要某个模块没有导出被引用,并且该模块被标记为无副作用,就直接把整个模块从依赖图中移除。这样,lodash-es 中那些没有被业务代码触达的内部模块,也会像被黑洞吞噬一样消失。这就是“放弃宇宙”的含义:不只是一个模块的内部清理,而是把整条未使用的依赖路径从构建结果中彻底抹除。
此外,Webpack 5 对 optimization.usedExports 和 optimization.sideEffects 的默认行为做了优化。在开发模式下,tree shaking 默认关闭以保证构建速度;但在生产模式下,Webpack 5 会自动启用这些优化,并且对 ESM 模块的边界判断更加准确。这使得开发者很少需要手动配置,就能体会到比 Webpack 4 更明显的体积下降。
实现机制:sideEffects 标记、模块合并与代码分割
要让 Webpack 5 敢于放弃整个宇宙,最核心的手段是给模块打上无副作用的标签。在 package.json 中设置 "sideEffects": false,等于告诉打包器:这个包里的所有模块都可以在未被引用时被安全删除。对于包含 CSS 文件的项目,不能简单粗暴地设置 false,因为 CSS 文件本身就可能被 import 而没有任何导出,如果标记为无副作用,CSS 会被错误删除。正确的做法是使用数组形式,把 CSS 文件排除在外:
{
"name": "my-project",
"sideEffects": [
"*.css",
"*.scss"
]
}
这里 *.css 和 *.scss 使用了通配符,表示所有 CSS 文件都具有副作用,不能被随意删除。其他 JS 模块则默认无副作用。这样配置后,Webpack 5 在构建时就能更激进地裁剪依赖图。需要注意的是,第三方库如果本身没有在 package.json 中提供 sideEffects 字段,Webpack 会默认认为它们有副作用,从而保留整包。为了让这类库也能被“放弃”,可以在自己的 package.json 中使用 sideEffects 的数组形式,手动声明特定第三方包的模块无副作用,或者使用 Webpack 的 module.rules 配合 sideEffects 规则进行覆盖。
另一个重要机制是模块合并(Module Concatenation),也被称为作用域提升。Webpack 5 会把多个被引用的小模块合并到一个闭包内,减少 bundle 中的包裹函数数量。这不只减少了代码体积,也提高了运行时性能。因为模块之间的引用不再经过多次函数调用,而是直接访问同一作用域内的变量。这个优化在 Webpack 5 中是默认开启的,但前提是模块必须是 ESM 且没有被动态导入等分隔。结合 sideEffects 标记,模块合并能把已经裁剪过的少量模块进一步压缩,让最终产物更加紧凑。
代码分割同样在“放弃宇宙”中扮演关键角色。通过动态 import() 或 optimization.splitChunks 配置,可以把不需要首屏加载的依赖拆分成独立的异步 chunk。这样即使某些宇宙没有被完全删除,也至少不会阻塞首屏渲染。Webpack 5 对 splitChunks 的默认配置已经比较合理,但根据业务场景调整 cacheGroups 可以进一步细化。例如,把 node_modules 中的第三方库单独打包,与业务代码分离,便于浏览器缓存,也能更清晰地看到哪些依赖体积过大。
实战配置与体积对比:放弃宇宙能省多少 KB
下面通过一个简单项目展示配置前后的差异。假设项目入口文件 src/index.js 引入了两个工具模块,其中一个模块完全未被使用,另一个模块只使用了其中一个导出。未做任何 sideEffects 优化时,Webpack 5 生产构建的 bundle 大小可能包含整个未使用模块的代码。在 package.json 中为项目自身模块添加 "sideEffects": false 后,重新构建,未使用模块会被整体删除。使用 webpack-bundle-analyzer 可以直观看到,原本占据体积的模块树分支直接消失。
// webpack.config.js
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: '[name].[contenthash].js',
clean: true
},
optimization: {
usedExports: true,
sideEffects: true,
concatenateModules: true,
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: -10
}
}
}
}
};
上面的配置中,usedExports: true 表示启用导出级 tree shaking,sideEffects: true 表示读取 package.json 中的 sideEffects 字段,concatenateModules: true 启用作用域提升。需要注意的是,sideEffects 在这里是 optimization 配置项,与 package.json 中的字段同名但作用不同:前者是告诉 Webpack 是否要分析并利用 sideEffects 标记,后者是开发者对模块副作用的声明。两个配置同时生效,才能实现完整的模块级删除。
实际测试中,一个包含多个工具函数但只使用其中两个的项目,在开启 sideEffects 优化后,bundle 体积减少了约 30% 到 50%,具体数值取决于未使用代码的占比。如果项目引用了大量第三方组件库,但只用了其中一两个组件,配合库自身的 sideEffects 标记,体积下降会更明显。例如使用 Ant Design 的按需加载插件,或者直接在 babel-plugin-import 中配置,本质上也是通过替换导入路径和利用 tree shaking 来“放弃”未使用的组件宇宙。
不过,放弃宇宙也要注意几个坑。第一,CSS 文件必须显式标记为有副作用,否则会被误删。第二,某些库在顶层执行了必要的初始化操作,即使没有导出,也不能简单标记为无副作用。第三,动态加载的模块如果被拆分为异步 chunk,sideEffects 的分析范围会有所不同,需要确认异步 chunk 中的模块是否真的可以被删除。第四,使用 sideEffects: false 时,要确保项目自身模块确实没有顶层副作用,否则可能导致运行时报错。建议在配置后先跑一遍完整的单元测试和端到端测试,确保行为没有变化。
总结一下,Abandoning Universe 并不是某个独立开关,而是 Webpack 5 对 tree shaking、sideEffects、模块合并与代码分割的组合运用。它让“能删就删”从口号变成可执行的构建策略。如果你的项目还在被 bundle 体积困扰,不妨从 package.json 的 sideEffects 字段开始,逐步开启 production 模式的优化选项,再用 bundle 分析工具找出那些可以被整个放弃的依赖宇宙。经过一轮清理,你可能会惊讶地发现,很多看似必需的依赖其实早已成为可以丢弃的负担。
Webpack 5tree shaking放弃宇宙修改时间:2026-10-06 05:39:08