Tree Shaking是一种通过静态分析代码依赖,剔除项目中未被引用代码片段的打包优化技术,核心目标是减少最终打包产物的体积,提升前端项目的加载效率。它并不是某款打包工具独有的功能,而是基于JavaScript模块系统的特性实现的通用优化思路。

Tree Shaking的核心原理
Tree Shaking生效的前提是模块系统支持静态分析,目前只有ES_Module(即使用import和export语法的模块)满足这个要求,因为ES Module的导入导出语句是静态的,在代码编译阶段就可以确定模块的依赖关系,不需要等到运行时。
其工作流程可以分为三个核心步骤:
- 第一步是标记阶段,打包工具会遍历所有模块,记录每个导出成员是否被其他模块引用,没有被引用的导出会被标记为未使用。
- 第二步是删除阶段,在代码压缩环节,工具会将标记为未使用的导出代码以及对应的导入语句直接移除。
- 第三步是验证阶段,确保移除代码后不会影响原有功能的正常运行。
需要注意的是,CommonJS的require和module.exports是动态语法,打包工具无法在编译阶段确定依赖关系,因此无法触发Tree Shaking。
Tree Shaking的实践配置
基础环境准备
首先确保项目使用的是ES Module语法,以下是一个简单的示例代码结构:
// utils/math.js 导出多个工具函数
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const multiply = (a, b) => a * b;
// main.js 只导入add函数,subtract和multiply未被使用
import { add } from './utils/math.js';
console.log(add(1, 2));
Webpack中的基础配置
Webpack从2.0版本开始原生支持Tree Shaking,需要在配置文件中开启两个核心选项:
// webpack.config.js
module.exports = {
mode: 'production', // production模式下会自动开启Tree Shaking相关优化
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: require('path').resolve(__dirname, 'dist')
},
optimization: {
usedExports: true, // 标记未被使用的导出,development模式下也需要手动开启这个选项才能看到效果
}
};
如果是development模式,打包后的代码会保留未使用的导出,但会在注释中标记为unused harmony export,等到切换到production模式时,这些代码会被自动移除。
处理副作用代码
如果模块中包含副作用代码,比如直接执行的操作、修改全局对象的逻辑,Tree Shaking可能会误删必要代码,这时候需要在package.json中配置sideEffects字段:
{
"name": "tree-shaking-demo",
"sideEffects": false // 标记整个项目没有副作用代码,所有未使用的导出都可以被移除
// 如果有部分文件有副作用,可以配置为数组,比如 ["*.css"],表示css文件有副作用,不会被Tree Shaking处理
}
常见失效原因与避坑方法
很多开发者配置后发现Tree Shaking没有生效,通常是以下原因导致的:
- 使用了CommonJS语法,需要将
require和module.exports全部替换为import和export。 - 没有配置
sideEffects,或者错误标记了有副作用的文件,导致打包工具不敢移除未使用的代码。 - 使用了Babel等转译工具,默认会把ES Module转成CommonJS语法,需要在Babel配置中关闭这个转换:
// babel.config.json
{
"presets": [
["@babel/preset-env", {
"modules": false // 关闭ES Module到CommonJS的转换,保留静态语法让Tree Shaking生效
}]
]
}
另外需要注意,Tree Shaking只能移除模块级别未使用的导出,无法处理函数内部、语句块内部的冗余代码,这类优化需要依赖压缩工具的更细粒度分析能力。
Tree_Shaking打包优化WebpackES_Module修改时间:2026-06-18 19:18:30