Tree Shaking 是 ES2015 模块定义方式提供的一个特性。Webpack 通过静态的分析模块定义,可以知道模块中哪些代码被使用了,那么代码没有被使用过。从 Webpack 5 开始,Tree Shaking 功能更加强大,可以支持嵌套代码、CommonJS 规范定义的代码的 Tree Shaking.

Tree Shaking 示例

我们先定义一个包含不会被使用的代码的模块。

src/shake.js

const shake = () => console.log('shake');
const bake = () => console.log('bake');

export { shake, bake };
1
2
3
4

在应用代码中是只用其中一部分。

src/index.js

...
import { bake } from "./shake";

bake();
1
2
3
4

此时,执行 npm run build,查看构建输出的代码(dist/main.js),可以看到代码中只有 console.log("bake") 而没有 console.log("shake").

如果要与 TypeScript 配合使用,我们需要设置 compilerOptions.modulees2015。这么做是为了将 ES2015 的模块定义留给 Webpack 来处理。

包级别的 Tree Shaking

Webpack 同样支持针对 npm 包的 Tree Shaking。如果一个包需要支持 Tree Shaking,这个包需要将 ES2015 模块以外的代码都进行转换,然后通过 package.json 中的 module 字段指定 ES2015 模块的代码。这样 Webpack 就可以通过 module 找到 ES2015 的模块,然后应用 Tree Shaking。

如果需要与 Babel 一起使用,则需要设置 "modules": false,这样才能让 Webpack 来处理 ES2015 模块。

另外,需要注意,为了能更好的应用 Tree Shaking,如果包里没有产生副作用的代码,则可以在 package.json 中增加 "sideEffects": false 来显示标明。

另一种对第三方包进行 Tree Shaking 的方式是使用 babel-plugin-transform-importsopen in new window 这个包来对模块中的 import 语句做一些处理,使得 Webpack 能更好的进行 Tree Shaking。

总结

Tree Shaking 是一个很强大的功能,一个包如果要支持 Tree Shaking 的话,需要源代码使用 ES2015,同时在 package.json 中设置 module 字段。

Tree Shaking 会删除未被使用的代码。

如果要使用 Tree Shaking,需要以 ES2015 来编写源代码。

如果你是一个包的开发者,要想支持 Tree Shaking,则需要将源代码中非 ES2015 模块的代码进行必要的转换,同时可以借助于 "sideEffects": false 来让 Webpack 更好的应用 Tree Shaking.

关注微信公众号,获取最新推送~