关于 Tree Shaking 的探索
近期项目组的组件库需要维护,其中有关于组件按需加载采用 antd 组件库的方案,是通过 umijs/babel-plugin-import 来实现的。
这个方案实际上是通过分析语法,在编译阶段将模块引用转成通过相对路径来实现的。即
import { Button } from 'antd';
ReactDOM.render(<Button>xxxx</Button>);
↓ ↓ ↓ ↓ ↓ ↓
var _button = require('antd/lib/button');
ReactDOM.render(<_button>xxxx</_button>);
然而这个方案实际上早在很久之前已经被 antd 官方抛弃了,antd 目前的是通过 tree shaking 实现 JS 部分的按需加载而, css 方面则认为性价比不高等原因没有额外处理,略有争议,详细可以参考 https://github.com/ant-design/ant-design/issues/23988 这个 issue 里的相关讨论。
鉴于 webpack 文档里关于 tree shaking 的篇章写的比较晦涩。在早些时候有做过一些[测试以及总结]( 关于 webpack 的 tree shaking),但当时的理解比较不够到位。
本次借着重新梳理组件库的机会,在这个 test-webpack-tree-shaking-demo 中再次更为全面地测试并整理 webpack tree shaking 相关内容,目前主要应用 webpack 的版本仍然处于 webpack4,因此本项目也都是基于 webpack4,如有理解不到位的地方还望指出探讨。
webpack 能标识出 dead code 的前提是使用 esm 规范来编写代码(在 webpack5 是新增了部分 commonjs 的支持)。
而标识 dead code 主要通过一下三种方式:
- 通过 usedExports 标识
- 通过 sideEffects 标识
- 通过 /#PURE/ 标识
webpack 标识出 dead code 之后,再通过 terser 等压缩工具,将这些代码移除,从而实现 tree shaking。
对于上述结论的验证,专门写了个测试的项目 https://github.com/KNighD/test-webpack-tree-shaking-demo,请移步 GitHub 继续阅读。