tree shaking 保守保留有副作用代码,关键在于消除顶层副作用、使用纯esm、精准声明sideeffects,并配置构建工具以确保静态分析有效。

Tree Shaking 本身不会“强制剔除副作用”,恰恰相反——它会保守保留有副作用的代码,防止误删。所谓“强制剔除无用类中函数声明的副作用”,本质是消除副作用本身,让这些函数真正变成可被安全摇掉的纯导出。关键不在“强制剔除”,而在“让工具确认它们没有副作用”。
确保模块是纯ESM且无顶层副作用
Tree Shaking 只对 ES6 模块(import/export)生效,且要求模块本身不带运行时影响。如果一个类或函数在模块顶层就执行、修改全局、注入样式或调用 API,Webpack 就会认为整个文件有副作用,跳过摇树。
- 把初始化逻辑移到函数内部,而不是模块顶层:避免
console.log('init')、window.xxx = ...、document.head.appendChild(...)等写法 - 类定义本身不触发副作用,但若类中有静态块或立即执行的 getter/setter,也要移除或惰性化
- 检查你导入的类是否来自 CJS 包(如旧版 lodash),这类模块无法被静态分析,应改用 ESM 兼容版本或按需引入路径
在 package.json 中精准声明 sideEffects
这是告诉打包工具“哪些文件确实需要保留,其余都可放心摇”。不要笼统设为 false 后又偷偷塞副作用,而要诚实标注。
- 如果你的类文件(如
utils/number.ts)只导出纯函数,且无任何顶层执行,就在项目或库的package.json中写:"sideEffects": false - 如果只有个别文件含副作用(比如
setup.ts里注册了全局插件),就显式列出:"sideEffects": ["./src/setup.ts", "*.css"] - 注意:路径必须匹配实际打包路径(经 Babel/TS 处理后的 .js 文件路径),不是源码路径
配合构建配置关闭副作用干扰项
即使代码干净,错误的构建配置也会破坏 Tree Shaking 效果。
- Webpack 配置中确保
mode: 'production',并启用usedExports: true(标记未使用导出)和minimize: true(交由 Terser 删除) - Babel 必须禁用模块转换:
"modules": false,否则 import/export 被转成 require,静态分析失效 - TypeScript 用户需确认
compilerOptions.module为"ESNext"或"ES2020",且未启用isolatedModules: false导致非标准导出
验证函数是否真被剔除
别只信配置,要实测。方法很简单:
- 在类中加一个明显不会被调用的函数,例如
export function _DEBUG_ONLY() { debugger; } - 构建后搜索 dist/bundle.js,看该函数名是否存在;若存在,说明它被保留了——要么被间接引用,要么所在文件因副作用未被分析
- 用
webpack-bundle-analyzer查看模块依赖图,确认该类文件是否被标记为 “unused exports”











