Tree Shaking 失败主因是模块被误判有副作用,需检查 package.json 的 "sideEffects" 字段、识别隐式副作用代码、利用 Webpack stats 和可视化工具定位、确保纯 ESM 语法。

Tree Shaking 失败常因模块被误判为“有副作用”,导致本可移除的代码被保留。排查关键在于识别并显式声明哪些模块/代码**确实无副作用**,以及哪些地方**意外引入了副作用**。
检查 package.json 中的 "sideEffects" 字段
这是最常见原因。Webpack 依赖该字段判断模块是否可安全摇树:
- 若设为
false,表示整个包无副作用,所有未引用导出都可删除 —— 但若包里实际有副作用(如 CSS 注入、全局 polyfill、localStorage初始化),就会出错或功能异常; - 若设为数组(如
["*.css", "index.js"]),只声明明确有副作用的文件,其余默认视为无副作用; - 常见错误:把第三方 UI 库(如 antd)的样式入口写进
sideEffects,但自己项目中又通过import 'xxx.css'单独引入,却没在数组中声明,Webpack 就可能误删该 CSS。
识别代码中隐式副作用
以下写法会让 Webpack 认为模块有副作用,从而保留整块代码:
-
顶层赋值或调用:比如
console.log('init')、window.myLib = {...}、localStorage.setItem('flag', '1'); -
直接修改原型:如
Array.prototype.customMap = ...; -
动态
import()或eval:即使没执行,Webpack 也会保守保留; -
带副作用的导入:如
import 'core-js/stable'或import './reset.css',它们没有导出,纯靠执行产生效果 —— 这类必须显式列入sideEffects数组,否则 Webpack 可能把它和真正用不到的逻辑一起删掉。
利用 Webpack 的 stats 和可视化工具定位
构建时开启详细统计,确认哪些模块未被摇树:
立即学习“Java免费学习笔记(深入)”;
- 加参数
--stats=verbose或配置stats: { usedExports: true },查看每个模块的usedExports字段,false表示导出未被使用但仍被保留 —— 很可能因副作用标记或依赖链中断; - 用 Webpack Bundle Analyzer 查看产物构成,找到体积异常大的模块,再逆向查它为何没被剔除;
- 临时将疑似模块的
sideEffects设为false(仅测试),若构建报错或运行异常,说明它真有副作用,需保留在白名单中。
确保 ES 模块语法纯净,避免 CommonJS 混用
混合使用 import/export 和 require/module.exports 会破坏静态分析:
- Webpack 对
require的调用无法做可靠摇树(尤其动态路径),尽量全用 ESM; - 避免在 ESM 文件中写
module.exports = ...或exports.xxx = ...,这会让 Webpack 放弃对该模块的导出分析; - 第三方库若用 CommonJS,可通过
resolve.alias指向其 ESM 版本(如lodash-es替代lodash)。


















