webpack5 的 treeshaking 性能为什么强?

374 阅读2分钟

1. 嵌套 tree-shaking (Nested tree-shaking)

webpack5 可以追寻到嵌套的 exports,这可以在多次 exports 的时候提升 tree-shaking 的性能

// inner.js
export const a = 1;
export const b = 2;

// module.js
export * as inner from './inner';
// or import * as inner from './inner'; export { inner };

// user.js
import * as module from './module';
console.log(module.inner.a);

在上面这个例子中,inner 里的数据被多次 exports 了(inner.js一次,module.js一次),最终在 user.js 中使用,这时在 production 模式下,b 会被 shaking 掉。

2. 模块内部的 tree-shaking(Inner-module tree-shaking)

例如下述代码

// module.js
import { something } from './something';

function usingSomething() {
  return something;
}

export function test() {
  return usingSomething();
}

在 w4 的时候,w4 认为 module.js 引入了 something 并且 使用了 something,所以 something 不会被删除

当进入了 w5 时代,判断更加精确,它会监测出只有 module.js 里的 test 使用了 usingSomething 接着使用了 something。而 testusingSomething,在 module.js 里并没有使用,而仅仅是导出出去了。也就是说,当 module.js 里的 test 未被其他文件引用时,其本身引入 something 会被删除

  • 副作用 (w4 就有了)

而当 package.json 里设置 "sideEffects": false 时,判断则会更加精确,当且仅当 test 被其他文件引入并被使用时,才不会删除,否则将被『摇下来』

sideEffects 就是副作用,"sideEffects": false 则意味该包没有副作用,若没有使用,则可以删除

更详细的信息:optimization.sideEffects

3. CommonJs Tree Shaking

CommonJs 的 tree-shaking 一直是不在考虑范围之内的,因为它是动态的。但是 w5 提供了对一些 CommonJs 结构检测的支持,当 CommonJs 里的某些导出未被使用时,将被删除。并且 w5 可以通过 require() 的调用跟踪一些相关的导出变量

由于性能原因,当 w5 遇到不可分析的代码结构时,将直接终止跟踪。具体哪些代码结构可以分析,详见官网: CommonJs Tree Shaking

4. Side-Effect analysis

前面我们知道当第三方包的 package.json 设置了 "sideEffects": false, 将会将该包认为是无副作用的。

而同时,w5 也会自行分析各个包,并标记其是否是无副作用

5. 每一次 runtime 都做优化

一个 Runtime 可以理解为一个入口(entryPoints),w5 现在默认地可以在每一次运行时都去优化模块。这可以确保每个导出的代码是真正被当前入口所需要的。

6. 整体的 tree-shaking 升级

  • w5 之前,认为 export defalut 是必然会被使用的,所以不会 tree shaking 掉,但是 w5 之后,会做更优的判断其是否被使用

  • w5 会对于冲突的 export 会有提示

  • es module 的动态引入 import() 也将支持 tree shaking,通过使用 magic comment 可以实现,eg:/* webpackExports: ["abc", "default"] */

更多详情请关注官网:webpack.js.org/blog/2020-1…