tree shaking 不保证无副作用,需主动声明;副作用指无导出却影响外部的代码,如插入样式、修改全局对象;须用 package.json 的 sideeffects 字段显式标注,否则会被误删。

Tree Shaking 本身不“保证”代码无副作用,它只是依赖你**主动声明**哪些模块有副作用,从而避免误删。真正让执行安全的,是你对副作用的识别、隔离和显式标注。
副作用是什么,为什么必须处理
副作用指模块在导入或执行时,不通过 export 暴露任何值,却直接产生外部影响,例如:
- 向
document.head插入样式表 - 调用
localStorage.setItem() - 修改全局对象(如
Array.prototype.map = ...) - 注册事件监听器或启动定时器
- 执行 SDK 初始化(如
Analytics.init())
这类代码没有导出,也没有被任何变量接收,Tree Shaking 会认为“没人用它”,直接剔除——结果就是样式丢失、功能失效。
用 sideEffects 字段明确告诉打包工具
在库或项目的 package.json 中设置 sideEffects 字段,是关键一步:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
-
"sideEffects": false:表示所有模块都无副作用,可放心摇树(推荐用于纯工具库) -
"sideEffects": ["*.css", "*.scss", "src/polyfill.js"]:只保留匹配的文件,其余仍可分析剔除 -
"sideEffects": ["./src/init.js"]:仅该文件有副作用,其他导出不受影响
注意:import './index.css' 这类语句默认被视为有副作用,但若未在 sideEffects 中列出,Webpack 5+ 仍可能删掉它——所以 CSS 文件必须显式声明。
把副作用代码从普通模块中抽离出来
不要把副作用逻辑混在工具函数里。比如下面写法很危险:
/* utils.js —— ❌ 危险:副作用藏在工具模块里 */
console.log('utils loaded'); // 副作用
export const debounce = () => { /* ... */ };应改为:
- 新建独立入口文件(如
entry-with-effects.js),专门做初始化 - 把副作用代码移到该文件顶层,且不导出任何东西
- 在
sideEffects中只列这个文件 - 主业务代码保持纯净,只做导出/导入
验证副作用是否被正确保留
最直接的方式是构建后检查产物:
- 搜索你期望保留的副作用代码(如某段
document.createElement调用),确认它出现在最终 bundle 中 - 临时注释掉
sideEffects字段,再构建——如果副作用代码消失了,说明原先配置生效了 - 使用
webpack-bundle-analyzer查看模块图谱,观察副作用文件是否被标记为“used”
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










