tree shaking 能否真正生效取决于模块格式、导出方式、构建配置和导入写法四者严格对齐:必须使用 es module(import/export)、禁用 commonjs、第三方库选 esm 版本(如 lodash-es)、具名导出、配置 sideeffects 并确保构建产物为 es 格式。

Tree Shaking 能否真正生效,不取决于“开了没开”,而取决于模块格式、导出方式、构建配置和导入写法这四者的严格对齐。Rollup 原生强支持,Vite 底层用 Rollup,所以两者配置逻辑高度一致——关键在细节。
确保代码和依赖都走 ESM 路线
Rollup/Vite 的 Tree Shaking 依赖静态分析,只对 ES 模块(import/export)有效。CommonJS(require/module.exports)会直接阻断整个链条。
- 你的源码必须用
export const fn = () => {},禁用module.exports = {} - tsconfig.json 中设
"module": "esnext",不能是"commonjs" - 第三方库要选 ESM 版本:比如用
lodash-es替代lodash;检查包的package.json是否含"exports": { ".": { "import": "...mjs" } }或"module": "dist/index.es.js"
子包或工具库必须规范声明入口与类型
如果你在 Monorepo 中开发可被引用的子包(如 @org/ui),它的 package.json 决定上层能否摇树。
- 必须设
"type": "module",否则所有.js文件按 CommonJS 解析 -
"module"字段指向 ESM 入口(如dist/index.es.js),这是 Vite/Rollup 优先读取的 - 推荐用
"exports"替代main/module,支持更细粒度控制,例如:"./button": { "import": "./dist/button.es.js" },让按路径导入也能摇树 - 构建产物不能是
preserveModules: true,那会保留原始目录结构,破坏模块图分析
Vite 或 Rollup 构建配置要点
Vite 默认开启 Tree Shaking,但需确认几项关键配置不被覆盖或误关。
- Vite 中无需额外开启
build.treeshake,但建议显式设为true,避免插件干扰 - 确保
build.minify启用(如'terser'),压缩阶段才真正移除死代码 - Rollup 配置中,
output.format必须是'es'或'esm',禁用'umd'或'iife' - 若引入了 CJS 第三方包,加
vite-plugin-commonjs插件转换,再配合treeshake: true
声明副作用,释放摇树权限
Rollup 默认保守:只要它不确定某文件是否“有副作用”,就会整块保留。你需要主动声明哪些文件可以安全删除。
- 在项目根目录
package.json中添加"sideEffects"字段 - 值为
false表示全项目无副作用(适合纯函数库) - 值为数组时,列出有副作用的文件,如:
["*.css", "src/polyfill.ts"],其余都可摇 - 注意:CSS、字体、SVG 导入默认视为有副作用,不声明就无法摇掉未使用的样式模块











