如何确认树摇动是否与Webpack 2一起使用?

jas*_*san 7 reactjs webpack webpack-2 tree-shaking

我刚刚将我的反应应用程序从webpack 1更新到webpack 2.但是,我的捆绑包大小增加了~30Kb.我希望捆绑的大小会减少,我怎么能确认树摇动的效果.为什么增加?

Van*_*uan 5

TL;DR:从 2.3 版本开始,webpack 没有任何 tree shake 功能。它只是使用 UglifyJS 来删除未使用的代码。


首先我们必须定义什么是树木抖动。

  • Stackoverflow 将其定义为“现代 JavaScript 的死代码消除算法”。

  • Webpack 澄清其模块系统的静态结构依赖于 ES2015 模块导入/导出。

  • Rollup(最初普及该术语)也有类似的解释。

所以我们可以推导出一个具体的定义:静态排除未使用的ES模块导出。

现在,让我们看看每个模块通常有哪些转换阶段:

  • babel-loader 被提供一个入口点,它是某种模块格式的 javascript 文件。Babel 可以将其转换为另一种模块格式或保持原样 ( module: false)
  • webpack 将静态解析文件并查找导入的模块(使用某种正则表达式)
  • webpack 将转换模块格式(如果 babel 尚未转换它)或添加一些包装器(对于 commonjs 模块)
  • 导入的模块成为入口点并转到 babel-loader
  • 加载并转换所有模块后,uglify 将处理结果包并删除未使用的代码 ( unused: true)

现在,我们可以看到,虽然 uglify 可以删除未使用的导出,但它实际上并不依赖于 ES 模块语法。这只是一种通用的死代码消除,因此不能将其定义为“Tree shake”。

那么如何确认webpack是否有tree shake呢?

  • 首先,所有代码必须是ES模块格式。
  • 正如另一个答案中已经提到的,我们必须禁用 Uglify。
  • 我们还必须禁用 babel 的模块转换,因为我们无法知道该阶段是否使用了模块。

现在,如果 webpack 实际上实现了树摇算法,我们可以通过查看此入口点的包大小来确认它:

import { keyBy } from 'lodash-es'; // lodash is in ES module format

console.log(keyBy([{ key: 'value' }], 'key'));
Run Code Online (Sandbox Code Playgroud)

如果 webpack 确实有 tree shake,结果应该是几十 KB。如果没有,它将是半兆字节或更多。


小智 3

您可以采取以下几个步骤:

  1. 关闭缩小/丑化
  2. 在一些您知道未使用的函数中插入注释
  3. 检查输出以查看这些注释是否存在

Webpack 还可以显示每个导入模块/包的大小。例如,在工作中,我们有一个包含 lodash 和 underscore 的包,因为我们使用的库之一需要它们中的每一个;webpack 清楚地显示每个包添加了多少千字节:

lodash 和 underscore 的 webpack 包大小

您应该能够从中看出尺寸的增加来自何处。

  • 我按照 webpack 迁移指南进行更新。因此,对于步骤 1,我应该设置 **minimize: false; 在 LoaderOptionsPlugin** 中或者只是从生产环境插件中删除 uglify,对于步骤 2,我是否搜索捆绑的 js 文件以查看是否包含注释? (2认同)