主题
Tree Shaking
Tree-shaking (摇树优化)是一种通过静态分析消除 JavaScript 代码中未使用部分的技术,旨在减少最终构建产物体积,提升加载速度和运行效率。其名称源自“摇晃树干使枯叶掉落”的比喻,核心思想是去除未被引用的“死代码”(Dead Code)。
Tree-shaking 的作用
减少打包体积
- 通过删除未使用的模块、函数或变量(如第三方库中未被调用的方法),显著缩小代码体积;
优化性能
- 减少网络传输时间和内存占用,提升页面加载速度,尤其对移动端和低带宽环境效果明显;
支持按需加载
- 结合模块化开发,实现按需引入功能(如仅导入组件库中的特定组件);
生产环境优化
- 在 Webpack 生产模式(
mode: 'production'
)下默认启用,结合代码压缩工具(如Terser
)进一步优化。
- 在 Webpack 生产模式(
Tree-shaking 的工作原理
静态分析依赖关系
- 基于 ES Module:ES6 模块的导入(
import
)和导出(export
)是静态的,依赖关系在编译时即可确定,支持可靠的分析。 - 构建依赖树:从入口文件出发,解析所有模块的依赖关系,形成抽象语法树(AST)。
- 基于 ES Module:ES6 模块的导入(
标记未使用代码
- 通过工具(如 Webpack)标记未被引用的导出项(如函数、变量),如添加
/* unused harmony export */
注释。
- 通过工具(如 Webpack)标记未被引用的导出项(如函数、变量),如添加
删除死代码
- 结合压缩工具(如
Terser
、UglifyJS
)将标记的代码从最终产物中移除。
- 结合压缩工具(如
js
// 示例 utils.js
export function a() { } // 被标记为未使用
export function b() { } // 被使用
// 打包后仅保留 function b() {}
Tree-shaking 的注意事项
必须使用 ES Module 语法
- CommonJS(如
require / module.exports
)因动态依赖特性无法被静态分析,Tree-shaking 仅对 ES Module 有效。
- CommonJS(如
避免副作用代码(Side Effects)
- 副作用代码(如修改全局变量、执行立即函数)可能被误删,需通过
package.json
的"sideEffects"
字段标注:- false:所有文件无副作用,可安全删除未使用代码。
- ["*.css"]:指定含副作用的文件(如 CSS 导入)。
- 副作用代码(如修改全局变量、执行立即函数)可能被误删,需通过
配置 Babel 避免破坏 ES Module
- Babel 默认将 ES Module 转换为 CommonJS,需设置
preset-env
的modules: false
保留原始语法。
- Babel 默认将 ES Module 转换为 CommonJS,需设置
生产环境优化
- Webpack 需配置
mode: 'production'
以启用压缩和 Tree-shaking。
- Webpack 需配置
第三方库的兼容性
- 确保第三方库使用 ES Module 导出(如 Lodash 的 ESM 版本
lodash-es
)。
- 确保第三方库使用 ES Module 导出(如 Lodash 的 ESM 版本
Tree-shaking 的局限性
动态导入无法分析
- 如
import()
动态加载的模块需结合代码分割(Code Splitting)优化。
- 如
默认导出对象难以优化
js
// 无法判断对象中哪些属性被使用
export default { a : 1 , b : 2 };
无法处理运行时依赖
- 如通过字符串拼接生成的模块路径(如
require('module/' + path)
)。
- 如通过字符串拼接生成的模块路径(如