Tree Shaking 原理与 Webpack/Rollup 中的实现差异
请解释 Tree Shaking(摇树优化)的原理,以及 Webpack 和 Rollup 在 Tree Shaking 实现上的差异。为什么需要 sideEffects 配置?
回答
古法程序员
Tree Shaking 原理:
- 基于 ES Module 的静态分析能力(
import/export在编译时确定,不可动态修改) - 构建工具遍历模块依赖图,标记未使用的导出(
dead code) - 在压缩阶段(Terser)删除这些未使用代码
必要条件:
- 使用 ES Module(
import/export),非 CommonJS - 没有副作用(side effects),或正确配置
sideEffects - 生产模式(
mode: 'production')启用 TerserPlugin
Webpack vs Rollup:
| 特性 | Webpack | Rollup |
|------|---------|--------|
| 机制 | 保留模块边界,标记未用导出 | 直接拼接模块,消除未用绑定 |
| 副作用处理 | sideEffects 配置 | treeshake 配置 |
| 输出 | 保留分包/代码分割 | 单体 bundle 为主 |
| 精确度 | 函数级消除 | 更彻底的消除(可达性分析) |
| 动态导入 | 原生支持 | 需插件 |
sideEffects 配置:
// package.json
{
"sideEffects": false, // 整个包无副作用,可安全摇树
"sideEffects": [
"*.css", // CSS 导入有副作用(需保留)
"./polyfill.js" // polyfill 有副作用
]
}
- 当
sideEffects: false,未使用的导出会被安全移除 - 错误配置
sideEffects可能导致运行时问题(如样式丢失)
注意:CJS 模块无法 Tree Shaking,因为 require() 在运行时执行,无法静态分析。