tree-shaking 依赖打包器对 es 模块静态结构的识别,需用 named export/import、设 "module": "esnext"、声明 "sideeffects"、生产构建验证;错误用法(如 default export + 解构)或副作用未标注会导致失效。

Tree-shaking 不是开关,而是依赖打包器对 ES 模块静态结构的识别能力。只要满足基本前提,现代工具(Webpack、Rollup、Vite)默认就能剔除未使用的函数声明——关键在于“怎么配”不在于“开不开”,而在于避免破坏它的运行条件。
确保使用 ES 模块语法
这是 Tree-shaking 的基础。所有自定义模块必须用 named export / import,不能用 default export + 对象解构式调用。
- ✅ 正确:在
utils.js中写export const format = () => {};,在入口中写import { format } from './utils.js'; - ❌ 错误:写
export default { format, parse };,再用import utils from './utils.js'; utils.format();—— 整个对象会被保留 - ⚠️ 注意:TypeScript 项目需在
tsconfig.json中设"module": "esnext",否则 tsc 可能转成 CommonJS,破坏静态分析
避免副作用干扰判断
打包器默认假设每个模块都有副作用(比如修改全局变量、发起请求、操作 DOM),因此不敢删任何导出。你需要主动告诉它:“这部分代码是纯的”。
- 在项目根目录的
package.json中添加字段:"sideEffects": false(表示整个项目无副作用) - 如果某些文件确实有副作用(如 CSS 导入、polyfill 脚本),可改用数组形式:
"sideEffects": ["*.css", "src/polyfill.js"] - 第三方库若已标注
sideEffects: false(如lodash-es、date-fns),优先选用;否则手动指定子路径导入,例如import debounce from 'lodash-es/debounce'
检查构建模式与配置细节
开发模式下 Tree-shaking 通常不生效或不可见,务必在生产构建后验证结果。
- Webpack:设
mode: 'production'即可自动启用usedExports和压缩;无需额外开启,但可显式加optimization: { usedExports: true }便于调试 - Rollup:默认全量启用,只要输出格式为
format: 'es'或'cjs'(且输入是 ESM) - Vite:开发时基于原生 ESM 按需加载,构建时自动应用 Tree-shaking;可通过
build.rollupOptions.treeshake: true显式确认 - 别被 source map 或 HMR 干扰:dev server 内存编译产物不反映真实体积,要查
dist/下的最终文件
验证是否真正生效
光看配置没用,得确认函数真的被删了。
- 构建后打开生成的 bundle 文件,搜索未使用的函数名(如
subtract),应找不到对应代码 - 用
source-map-explorer或rollup-plugin-visualizer可视化依赖和代码占比 - Webpack 构建加
--stats=verbose,查看输出中provided exports是否只列出你实际 import 的那些 - 注意陷阱:测试文件、类型导入(
import type)、IDE 自动补全残留的 import 语句,都会让函数“看似被引用”,导致无法剔除











