Tree Shaking 在 TypeScript + Vite 项目中需模块格式(ESM)、构建模式(生产+压缩)、导入方式(按需)、副作用声明(sideEffects)四者协同;tsconfig 必设 "module": "esnext",禁用 CommonJS,按需导入第三方库,Vite 构建启用 minify 和 treeshake,并显式声明 sideEffects。

Tree Shaking 在 TypeScript + Vite 项目中不是“开个开关”就能自动生效的,它依赖一整套协同配置:模块格式、构建模式、导入方式、副作用声明,缺一不可。重点不在“怎么配”,而在于“哪些环节必须对齐”。
确保 TypeScript 输出为 ES 模块
这是 Tree Shaking 的前提。Vite 默认支持 ESM,但 TypeScript 编译器若输出 CommonJS,就会彻底阻断摇树。
- 检查 tsconfig.json 中必须设为:
"module": "esnext"(不能是 "commonjs" 或 "amd")
"target": "es2020" 或更高(避免降级引入冗余 polyfill)
"importsNotUsedAsValues": "remove"(移除仅用于类型导入的 import,防止污染模块图) - 禁用 "outDir" 或 "declaration" 不影响运行时,但若同时启用了 "composite": true,需确认引用路径未意外触发全量编译
规范第三方库的导入写法
即使配置正确,错误的导入方式也会让 Tree Shaking 失效——工具无法判断你是否“用到了”。
- ❌ 避免全量导入:
import _ from 'lodash'→ 会保留整个 lodashimport * as THREE from 'three'→ 无法分析具体使用了哪些导出 - ✅ 改为按需导入:
import debounce from 'lodash/debounce'import { Vector3, Mesh } from 'three' - ⚠️ 注意库本身是否提供 ESM 版本:
优先选用lodash-es替代lodash;
查看包的package.json是否有"exports": { ".": { "import": "./dist/index.mjs" } }或"module": "./dist/esm/index.js"
Vite 构建配置显式启用优化
Vite 生产构建默认开启 Tree Shaking,但部分关键项需确认或补全:
-
build.minify 必须启用(如
'terser'或true),否则压缩阶段不触发摇树清理 -
build.terserOptions.module 设为
true,确保 Terser 以 ESM 模式解析(Vite 4.3+ 默认已设) -
build.rollupOptions.treeshake 可显式设为
true(非必需,但明确意图) - 若第三方库只有 CJS 版本,可加插件转换:
安装vite-plugin-commonjs并在vite.config.ts中启用,再配合treeshake: true
声明无副作用,释放摇树权限
Rollup(Vite 底层)默认保守:只要模块可能产生副作用,就整块保留。你需要主动“担保”。
- 在项目根目录的 package.json 中添加:
"sideEffects": false—— 表示所有源码文件无副作用(最激进,适合纯逻辑库)
或更安全地:"sideEffects": ["*.css", "*.scss", "src/polyfills.ts"]—— 只列出真正有副作用的文件 - 避免在模块顶层执行副作用操作,例如:
❌console.log('init')、document.body.appendChild(...)、fetch('/api/init')
✅ 把这些移到函数内部或组件生命周期里


















