- 构建依赖图:打包工具从入口文件开始,分析所有模块的导入导出关系
- 标记依赖:识别哪些导出被其他模块使用,哪些从未被引用
- 静态分析:基于 ES6 模块的静态结构(
import
/export
必须是顶层声明)
外观
外观
约 1303 字大约 4 分钟
2025-06-22
Tree Shaking 是现代 JavaScript 打包工具中实现 死代码消除(Dead Code Elimination) 的一项关键优化技术。
Tree Shaking 可以 显著减小打包后的文件体积,提高网页加载速度。
Tree Shaking 通过静态分析移除代码中未被使用的部分(就像摇树让枯叶落下一样),能够在打包时安全地移除:
Tree Shaking 的大致过程如下:
依赖关系分析阶段
import
/export
必须是顶层声明)代码标记阶段
package.json
的sideEffects
属性或 魔法注释 标记有副作用的模块代码消除阶段
优化输出阶段
End
从 Webpack 4 开始,Webpack 内置了 Terser
插件,用于压缩代码。Terser
插件集成了 Tree Shaking 功能,能够自动移除未使用的代码。
只要设置 mode
为 production
,Webpack 会自动启用该插件,无需手动配置。
module.exports = {
mode: "production",
// 其他配置...
};
在老版本的 Webpack 中,要开启 Tree Shaking,需要手动配置插件。
// webpack.config.js
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
// 其他配置...
optimization: {
minimizer: [
new TerserPlugin({
// 开启 Tree Shaking
treeShaking: true,
}),
],
},
};
// webpack.config.js
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = {
// 其他配置...
optimization: {
minimize: true,
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true, // 如果需要source map的话
}),
],
},
};
要配置 Webpack 实现代码的无用代码剔除,需要确保一下几点:
配置 mode
为 production
,Webpack 会自动启用相关优化。
module.exports = {
mode: "production",
// 其他配置...
};
Webpack 的 Tree Shaking 功能主要依赖于 ES 模块的静态结构。
import()
动态导入。在 Webpack 的 Tree Shaking 过程中,副作用 指的是模块执行时除了导出值之外的其他行为。这些行为可能包括:
window
上挂载对象eval
、with
如果直接删除有副作用的代码,可能导致代码运行时报错。因此,我们需要进行相关的配置,来告诉 Webpack 哪些模块是有副作用的,哪些模块是无副作用的。
sideEffects
属性在 package.json
中设置 sideEffects
为 false
,表示仓库下所有模块都没有副作用,Webpack 移除未使用的导出是安全的。如果存在有副作用的代码,我们可以配置一个数组来告诉 Webpack 保守处理。
{
// 标记所有的代码都没有副作用
"sideEffects": false
// 标记有副作用的文件
"sideEffects": [
"./src/some-side-effectful-file.js"
"./src/polyfill.js",
"*.css"
]
}
/*#__PURE__*/
注释标记函数、模块调用为无副作用,等于告诉 Webpack,如果该函数、模块未被调用,可以被安全的移除。
const result = /*#__PURE__*/ someFunction();
class MyClass {
constructor() {
/*#__PURE__*/ initPolyfill();
}
}
const value = /*#__PURE__*/ a + b * c;
尽量编写无副作用的模块。函数尽量是纯函数、尽量不导入其他的依赖、模块的导入不应该改变全局状态。
什么是纯函数?
一个函数的返回结果只依赖于它的参数,并且在执行过程中没有副作用,就称为纯函数。
假设模块 math.js
如下:
export function square(x) {
return x * x;
}
export function cube(x) {
console.log("cube"); // 副作用
return x * x * x;
}
如果只使用 square
,cube
中的 console.log
是副作用,Webpack 可能会因此不会移除 cube
。
1eb9b
-docs(Javascript): 更新Generator生成器函数文档内容于