tree shaking 起效的关键是静态导入,即顶层 import/export 语法,确保构建工具能静态分析依赖图谱并精准剔除未被显式引用的导出项,配合 production 模式与 terser 压缩完成最终删除。

要让 Tree Shaking 真正起效,关键在于让构建工具能“看懂”哪些导出项确实没被用到。Static Imports(静态导入)正是实现这一点的基础前提——它让依赖关系在编译时就完全确定,从而支持精准标记和剔除未使用的原始导出项。
必须使用顶层 import/export 语法
ES6 模块的静态特性要求所有导入导出语句必须出现在模块顶层,不能包裹在条件、循环或函数中。只有这样,打包工具才能通过 AST 静态分析构建完整的依赖图谱。
- ✅ 正确写法:
import { debounce, throttle } from 'lodash-es' - ❌ 错误写法:
if (env === 'prod') import('./utils')或const _ = require('lodash') - ⚠️ 注意:动态
import()返回 Promise,其加载的模块不参与 Tree Shaking
避免整体导入和命名空间导入
当使用 import * 或默认导入整个库时,构建工具无法判断具体用了哪些子功能,会保守保留全部导出,导致 shaking 失效。
- ✅ 推荐按需导入:
import { reactive, ref } from 'vue' - ❌ 不要写:
import Vue from 'vue'(Vue2 风格)或import * as utils from './utils' - ? 查看目标库是否提供 ESM 版本,例如用
lodash-es替代lodash,并确认其package.json中有"module"字段
确保导出项真正“未被引用”
Tree Shaking 剔除的是未被其他模块 显式引用 的导出项。即使某个函数在代码中定义了,只要没有被 import 或直接调用,就会被标记为 dead code。
- 例如:
export const unusedHelper = () => {}若无任何文件import { unusedHelper },它就不会进入最终 bundle - ⚠️ 但若该函数被父对象引用(如
export const api = { unusedHelper }),即使unusedHelper本身没被调用,也可能因对象整体被引入而保留 - ? 可配合
"sideEffects": false在package.json中声明项目无副作用,帮助工具更激进地剔除
配合生产模式与压缩器完成最终剔除
Static Imports 提供了分析基础,但真正删除代码发生在压缩阶段。Webpack 默认在 mode: 'production' 下启用 TerserPlugin,它会读取标记结果并移除未使用的导出声明。
- ✅ 确保构建命令使用
--mode production或配置mode: 'production' - ✅ 不要关闭
optimization.usedExports(Webpack 中默认开启) - ? 若使用自定义 minimizer,请确认其支持 dead code elimination,如 Terser 或 SWC










