跳到主要内容

谈谈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 的方式引入, 要当做有副作用的文件,以免在生产模式中被删除

json
{
"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