跳到主要内容

认识

2024年04月02日
柏拉文
越努力,越幸运

一、认识


Tree Shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如 importexport。这个术语和概念实际上是兴起于 ES2015 模块打包工具 rollup

Tree shaking 是基于 ES6 模板语法(importexports),主要是借助ES6模块的静态编译思想,在编译时就能确定模块的依赖关系,以及输入和输出的变量, 进而判断哪些模块已经加载, 哪些模块和变量未被使用或者引用,进而删除对应代码。

Tree Shaking 利用 ES6模块的特点,只能作为模块顶层语句出现。import的模块名只能是字符串常量。Tree Shaking 在去除冗余代码的过程中,程序会从入口文件出发,扫描所有的模块依赖,以及模块的子依赖,然后将它们链接起来形成一个抽象语法树(AST)。随后,运行所有代码,查看哪些代码是用到过的,做好标记。最后,再将抽象语法树中没有用到的代码摇落。经历这样一个过程后,就去除了没有用到的代码。

前提是模块必须采用 ES6 Module 语法,因为 Tree Shaking 依赖 ES6 的静态语法:importexport。不同于 ES6 ModuleCommonJS 支持动态加载模块,在加载前是无法确定模块是否有被调用,所以并不支持 Tree Shaking

二、使用


Webpack 中,启动 Tree Shaking 功能必须同时满足三个条件:

  1. 使用 ESM 规范编写模块代码

  2. 配置 optimization.usedExportstrue,启动标记功能

  3. 启动代码优化功能,可以通过如下方式实现:

    • 配置 mode = production

    • 配置 optimization.minimize = true

    • 提供 optimization.minimizer 数组

三、工作


Webpack 中,Tree-shaking 的实现,一是需要先标记出模块导出值中哪些没有被用过; 二是使用代码压缩插件 —— 如 Terser 删掉这些没被用到的导出变量。具体实现如下:

  1. Webpack 构建阶段: 收集模块导出变量并记录到模块依赖关系图 ModuleGraph 对象中

  2. Webpack 封装阶段: 遍历所有模块,标记模块导出变量有没有被使用

  3. 使用代码优化插件如 Terser,删除无效导出代码