webpack 在 mode: 'production' 下自动启用 tree shaking,依赖 optimization.usedexports、minimize 等默认配置协同工作,并要求代码使用 es6 模块、babel 不转换模块语法、且正确声明 sideeffects。

Webpack 在 mode: 'production' 下自动启用 Tree Shaking,靠的不是“魔法”,而是一整套协同工作的默认配置链。它不是单个开关,而是一系列前提条件和内置行为共同满足后自然生效的结果。
生产模式自动开启 Tree Shaking 的关键机制
-
mode: 'production'会默认启用optimization.usedExports: true(标记未使用导出) - 同时默认启用
optimization.minimize: true(触发 Terser 等压缩器执行死代码删除) - 自动设置
devtool: false,避免 sourcemap 干扰优化流程 - 默认关闭
optimization.concatenateModules: false(但实际在 production 下会启用模块合并,辅助分析)
这些组合让 Webpack 能在编译的 Make → Seal → Generate 阶段完成:
→ 收集所有 ES 模块的 export 声明
→ 追踪哪些导出被其他模块 import 引用
→ 标记未被引用的导出为“可移除”
→ 在生成最终 bundle 前,由 Terser 删除对应代码块
必须同时满足的三个硬性前提
代码必须用 ES6 模块语法(import/export)
CommonJS(require/module.exports)无法静态分析,Tree Shaking 完全不生效-
构建工具链不能把 ES6 模块转成 CommonJS
Babel 中必须设modules: false(禁用模块转换),否则import被转成require,静态依赖关系丢失// .babelrc { "presets": [["@babel/preset-env", { "modules": false }]] } -
没有副作用干扰(sideEffects)
若模块存在非导出的执行逻辑(如全局样式注入、polyfill 注册),需在package.json显式声明:{ "sideEffects": ["*.css", "*.scss"] }或设为
false(表示无副作用,整个模块可安全摇掉)
常见失效场景与快速自查
- ✅
import { debounce } from 'lodash-es'→ 可摇(ESM 版本) - ❌
import _ from 'lodash'→ 不可摇(CJS 版本,且整体打包) - ✅
export const foo = () => {}+import { foo } from './utils'→ 可摇未用项 - ❌
export default function() {}+import utils from './utils'→ 默认导出若没被解构引用,整个模块可能保留在 bundle 中 - ❌ Babel 把
export编译成Object.defineProperty(exports, ...)→ 静态分析失败,Tree Shaking 失效
本质上,mode: 'production' 是一条“信任契约”:你承诺提供符合 ESM 规范、无隐藏副作用、未被工具链破坏的代码,Webpack 就按约定帮你做静态裁剪。它不主动“开启”某个功能,而是移除开发模式下的保守保护,释放优化能力。











