Tree Shaking 是一种用于移除 JavaScript 代码中未使用部分(dead code)的优化技术。它的名字来源于“摇树”的比喻:通过摇动树,将枯叶(未使用的代码)抖落,只保留有用的部分。
1. Tree Shaking 的作用
- 减少打包体积:移除未使用的代码,减少最终打包文件的体积。
- 优化性能:减少加载和执行的代码量,提升应用性能。
2. Tree Shaking 的工作原理
Tree Shaking 的核心依赖于 ES6 模块系统 的静态结构特性。ES6 模块是静态的,意味着模块的依赖关系在编译时就可以确定,而不是在运行时。
关键点
静态分析:
- Webpack 在打包时会对模块进行静态分析,确定哪些代码被使用,哪些未被使用。
- 只有通过
import
导入且被实际使用的代码才会被打包,未使用的代码会被标记为“未使用”。
标记未使用的代码:
- Webpack 使用
terser-webpack-plugin
(或其他压缩工具)来标记和移除未使用的代码。
移除未使用的代码:
- 在生产环境中,Webpack 会自动启用 Tree Shaking,移除被标记为未使用的代码。
3. Tree Shaking 的使用条件
使用 ES6 模块语法:
- Tree Shaking 依赖于 ES6 的
import
和 export
语法。
- 如果使用 CommonJS 的
require
和 module.exports
,Tree Shaking 将无法生效。
启用生产模式:
- 在生产环境中,Webpack 会自动启用 Tree Shaking。
- 可以通过设置
mode: 'production'
来启用。
避免副作用:
- 如果模块包含副作用(如修改全局变量、立即执行的函数等),Webpack 无法确定这些代码是否可以安全移除。
- 可以通过在
package.json
中设置 "sideEffects": false
来明确模块没有副作用。
4. Tree Shaking 的配置
启用生产模式
module.exports = {
mode: 'production'
};
标记副作用
在 package.json
中标记模块是否有副作用:
{
"sideEffects": false // 表示模块没有副作用
}
或者指定有副作用的文件:
{
"sideEffects": [
"*.css", // CSS 文件有副作用
"*.global.js" // 某些全局脚本有副作用
]
}
5. Tree Shaking 的示例
未使用代码的模块
// math.js
export function add(a, b) {
return a b;
}
export function subtract(a, b) {
return a - b;
}
使用部分代码
// index.js
import { add } from './math';
console.log(add(1, 2)); // 只使用了 add 函数
打包结果
在启用 Tree Shaking 后,subtract
函数会被移除,因为它未被使用。
6. Tree Shaking 的注意事项
避免副作用:
- 如果模块包含副作用(如修改全局变量、立即执行的函数等),Webpack 无法确定这些代码是否可以安全移除。
- 可以通过在
package.json
中设置 "sideEffects": false
来明确模块没有副作用。
使用支持 Tree Shaking 的库:
- 确保第三方库使用 ES6 模块语法,并支持 Tree Shaking。
避免 Babel 转换模块语法:
7. Tree Shaking 的局限性
- 动态导入:
- 如果使用动态导入(如
import()
),Webpack 无法在静态分析时确定哪些代码会被使用。
- 副作用:
- 如果模块包含副作用,Webpack 无法安全移除未使用的代码。
总结
Tree Shaking 是一种通过静态分析移除未使用代码的优化技术,依赖于 ES6 模块的静态特性。它的核心步骤包括:
- 静态分析模块依赖关系。
- 标记未使用的代码。
- 在生产环境中移除未使用的代码。
通过合理配置和使用 Tree Shaking,可以显著减少打包体积,优化应用性能。