tree shaking 未生效主因是代码或配置不满足前提:未用 es module 语法、未在生产模式构建、存在副作用、模块被意外引用;需检查 import/export 是否被转为 commonjs、sideeffects 配置是否合理、依赖是否声明规范、有无动态导入或间接引用。

Tree Shaking 是基于 ES 模块静态结构(import/export)在构建时移除未使用代码的机制,但它有前提条件——只有当代码满足“可静态分析”且“无副作用”时,才能被安全剔除。检查和排查未被 Tree Shaking 掉的代码,核心是验证:是否导出被引用、是否触发了副作用、是否破坏了静态分析,以及构建工具是否按预期配置。
确认模块是否使用 ES Module 语法
CommonJS(require/module.exports)或动态 import() 无法被静态分析,会阻断 Tree Shaking 链路。
- 确保源码中只用
export和import,避免混用module.exports或exports.xxx - 检查第三方依赖:若它打包后是 CommonJS 格式(如
lodash),即使你用import { debounce } from 'lodash',整个包仍可能被打包进来;推荐改用更细粒度的包(如lodash.debounce)或启用 Webpack 的resolve.alias+sideEffects: false等配合 - 避免在
import前后插入运行时逻辑(如if (DEBUG) import(...)),这会让导入变成动态,失去静态性
检查 sideEffects 字段是否正确声明
package.json 中的 "sideEffects" 是告诉打包工具“哪些文件可能有副作用”,从而决定能否安全删除未引用的模块。设为 false 表示所有模块都无副作用,但若实际有(如 CSS 导入、全局 polyfill),会导致功能异常。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 项目根目录
package.json应明确列出有副作用的文件,例如:"sideEffects": ["*.css", "*.scss", "src/polyfill.js"] - 若漏写某个含副作用的文件(如一个执行
Element.prototype.extend的工具脚本),该文件可能被误删;反之,若错写成false且存在副作用,构建会出问题,但 Tree Shaking 可能“过度生效”——表面看删多了,实则是副作用没声明导致的连锁误判
利用构建产物反向验证未被摇掉的代码
最直接的方式是查看最终打包结果,定位“本不该出现”的代码。
- Webpack:启用
stats: "verbose"或使用webpack-bundle-analyzer,打开可视化报告,搜索疑似未使用的函数名或模块路径,看它是否出现在 chunk 中,并检查其引入链(谁import了它) - Vite:运行
vite build --report生成report.html,同样聚焦于“体积占比高但业务中未显式调用”的模块 - 关键技巧:在待排查函数内部加一句
console.log('xxx was bundled'),然后构建并搜索产物 JS 文件中是否存在该字符串——如果存在,说明它没被摇掉;再顺藤摸瓜查为何被保留(比如被某个间接引用链带入,或被/*#__PURE__*/注释遗漏)
留意常见“隐形保留”场景
有些代码看似没被调用,却因语言特性或构建配置被强制保留。
-
默认导出被解构导入:若模块只写
export default function foo(){},而你写import { foo } from './mod',ESLint 可能报错,但某些打包器会 fallback 到整个模块,导致无法摇树 -
具名导出但未用
export显式声明:比如const utils = { a() {}, b() {} }; export { utils },此时utils.a不会被单独摇掉,因为utils是一个整体对象导出;应改为export function a() {}和export function b() {} -
被
/*#__PURE__*/标记影响:这个注释用于标记“此调用可被移除”,但若误标在不可移除的副作用调用上(如/*#__PURE__*/ initStore()),可能导致初始化失效;反过来,若忘了标在纯函数调用上,某些压缩器(如 Terser)可能不敢删
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










