谈谈Tree-Shaking 实现原理
- webpack2.x开始⽀支持 tree shaking概念,顾名思义,"摇树"
- 通常用于移除 JavaScript 上下文中的未引用代码(dead-code 无生命的代码)
- 摇树 可以理解为 把没有用到的代码给移除下去,消除无用代码,不进行打包,
- 只支持ES module的引入方式!!!!
原理
-
treeShaking依赖ES6的静态语法 【ES module】
-
ES6 Module引入进行静态分析,故而编译的时候正确判断到底加载了那些模块- import命令会被js引擎静态分析
-
基于 ESM 的模块导入导出规则,可以实现静态编译时处理模块间的依赖
-
静态分析程序流,判断那些模块和变量未被使用或者引用,进而删除对应代码
实现
Tree-Shaking 的实现大致上可以分为三个步骤:
- 「构建」阶段,「收集」 模块导出变量并记录到模块依赖关系图 ModuleGraph 对象中;
- 遍历所有模块,「标记」 模块导出变量有没有被使用;
- 使用代码优化插件 —— 如 Terser,删除无效导出代码。
sideEffects理解
webpack 4添加了 sideEffects , 在 package.json 中添加这个属性, 表示,告知webpack是否存在副作用
- 基于 ESM 模块的项目, 很轻松的能分析到, 哪些文件是未使用的, 可以轻松 摇树掉的, 但是项目中没办法达到这种纯度, 所以,可以通过sideEffects方式,告知 webpack 怎么处理未使用的代码
1、在 package.json 中配置 sideEffects 为 false ,告知webpack 所有代码都没有副作用, 可以安全的删除
2、如果代码里有副作用, 我们通过给 sideEffects 配置一个数组, 告知webpack 哪些文件是 有副作用的, 不要被tree shaking 掉
使用场景:
1、比如css文件通过 import 的方式引入, 要当做有副作用的文件,以免在生产模式中被删除
{
"name": "your-project",
"sideEffects": ["*.css"]
}
如何使用 Tree-Shaking
Webpack5 中,Tree Shaking 在生产环境下默认启动, 如果要在开发环境启动 Tree Shaking,需要如下配置
-
使用 ESM 规范编写模块代码;
-
配置
optimization.usedExports为true,启动标记功能;- 未使用的导出内容不会被生成,导出名称会被处理做单个标记字符
-
package.json中,设置sideEffects,标记副作用
- 如果被标记为无副作用的模块没有被直接导出使用,打包工具会跳过进行模块的副作用,告知webpack是否存在副作用
-
启动代码优化功能,可以通过如下方式实现:
- 配置
mode = production; - 配置
optimization.minimize = true; - 提供
optimization.minimizer数组。
minimize启用压缩插件来压缩 bundle
- 配置