Webpack  | TreeShaking 工作原理

Webpack | TreeShaking 工作原理

阅读本文,你将了解

1. Tree Shaking 的工作流程

2. 实现 Tree Shaking 的前提

3. Tree Shaking 的副作用



目的

本质上为了消除无用的js代码,减少加载文件体积的方式,使其整体执行时间更短

那么如何判断js代码的“无用”?

这些无用的代码,又有另外一种叫法:Dead Code

而Dead Code 是被怎么定义的:

实现前提

  • Tree Shaking 的执行环境宿主一般是Node,而不是浏览器
  • 若JavaScript 是模块化的,那么必须遵循ES6 Module规范,而不是CommonJS或其他,主要是因为 ES6 Module 可以静态分析的。
    前者**通过作用域分析,分析出代码里变量所属的作用域以及他们之间的引用关系,进而可以推导出变量和导入依赖变量的引用关系**。
  • 将mode 选项为"production",以启用 tree shaking 和 minification (代码压缩)
  • 确保没有把compiler 将 es6 模块语法转换为CommonJS 模块。这一块很重要,在你使用babel-loader 或者 ts-loader 编译代码时,一定要保留import 和 export

原理

首先,Tree-Shaking实现分两步走,

Step 1:标记出模块导出值哪些没有被用过

Step 2:使用Terser删除掉没有被用到的导出语句

其中,标记过程又可以分为三个步骤:

  • Make 阶段,收集导出变量并记录到模块依赖图ModuleGraph 变量中。
  • Seal 阶段,遍历ModuleGraph 标记模块导出变量有没有被使用
  • 生成产物时,若变量没有被其他模块使用时则删除对应的导出语句
标记功能需要配置 optimization.useExports = true 开启

标记效果

webpack 负责对代码进行标记,把import & export 标记为3类:

  • 所有 import 标记为 /* harmony import */
  • 被使用过的 export 标记为/* harm export([type])*/ ,其中[type] 和 webpack 内部相关,可能是 binding,immutable 等等。
  • 未被使用过的 import 标记为 /* unused harmony export [FuncName] */,其中[FuncName] 为export 的方法名称

实例说明

标记

「注:省略了 bundle.js 上边 webpack 自定义的模块加载代码,那些都是固定的。」

由上可得:

  • bye 没有被使用,被标记为/* unused harmony export bye*/
  • hello 被使用为正常的 /*harmony export(imutable) */

删除

使用 Terser 就可以进行第二步,把 bye 彻底清除


副作用

副作用是函数式编程的一个概念,是指当调用函数时,除了返回函数值之外,还会对调用函数产生附加的影响。

简单来说,就是除了返回值以外,还做了其他事情。

比如

  • 打印Log
  • 读取和修改外部变量
  • 导入css文件,引入Polyfill 等

副作用代码不可被删除

举个例子:

const setTitle = ()=>{  // 
  document.title = "shenzhen";
}
const a = setTitle();

以上可知,虽然a变量没有被其他地方使用,但由于副作用,如果将其删除。

会导致document.title 没有成功被设置导致出现bug。

副作用出现原因

那有同学说了,不在项目中写带有副作用代码不就完了嘛?

只是难以预料的是,副作用代码很可能在编译阶段产生。

举个例子:


与此同时,如果我在第三个文件中注释掉 return Greet之后,Terser可以成功删除。

为什么呢?这是因为 return Greet 之后相当于给greet 变量赋值。而这个值在其他处有可能被修改。

而Terser(压缩代码工具),不能有效分析变量后续是否被引用、修改。

因此Terser不清楚以上代码是否产生副作用,因此保留。

总结

  1. Tree Shaking 用于减小文件体积
  2. 其工作流程是先标记,后删除
  3. 代码必须遵循 ES module 规范
  4. 删除代码失灵很可能因出现副作用代码导致

参考:

tree shaking失效了吗

Webpack 之 treeShaking

Tree-Shaking性能优化实践 - 原理篇

无用代码去哪了?项目减重之 rollup 的 Tree-shaking

深入浅出模块化(含 tree shaking)(下)

预告:下一篇着重介绍Tree Shaking 的实践中遇到的问题以及解决办法。

予人玫瑰,手有余香,如果您觉得内容不错,希望可以点赞关注,从而帮助到更多的人。


需要交流请加我个人微信:

编辑于 2024-03-29 10:55・IP 属地广东