【问题标题】:how to confirm if tree shaking is working with Webpack 2?如何确认摇树是否适用于 Webpack 2?
【发布时间】:2017-07-01 20:08:53
【问题描述】:

我刚刚将我的 react 应用程序从 webpack 1 更新到 webpack 2。但是,我的包大小增加了 ~30Kb。我希望捆绑包的大小会减小,我如何确认摇树有效。为什么会增加?

【问题讨论】:

    标签: reactjs webpack webpack-2 tree-shaking


    【解决方案1】:

    您可以采取几个步骤:

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

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

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

    【讨论】:

    • 我按照 webpack 迁移指南进行更新。所以对于第 1 步,我应该只设置 minimize: false;在 LoaderOptionsPlugin 中或只是从生产环境插件中删除 uglify,对于第 2 步,我是否搜索捆绑的 js 文件以查看是否包含 cmets?
    【解决方案2】:

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


    首先我们必须定义什么是摇树。

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

    • Webpack 阐明它依赖 ES2015 模块导入/导出来实现其模块系统的静态结构。

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

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

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

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

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

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

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

    现在,如果 webpack 真的实现了 tree shaking 算法,我们可以通过查看这个入口点的包大小来确认它:

    import { keyBy } from 'lodash-es'; // lodash is in ES module format
    
    console.log(keyBy([{ key: 'value' }], 'key'));
    

    如果 webpack 确实有树摇动,结果应该是几十 KB。如果不是,它将是半兆字节或更多。

    【讨论】:

      猜你喜欢
      • 2017-06-27
      • 2018-12-12
      • 2018-09-24
      • 2016-11-12
      • 2016-12-28
      • 2017-05-23
      • 2016-11-17
      • 2019-12-29
      • 2020-06-10
      相关资源
      最近更新 更多