webpack进阶用法实践3

102 阅读4分钟

提取页面公共资源

1.1 使用 externals+cdn

相比于 webpack进阶用法实践2 的 ****source-map 的结果的包的大小,小太多了;

1.2 使用 SplitChunksPlugin

SplitChunksPlugin | webpack 中文文档

1.2.1

1.2.2

1.2.3

1.2.4

默认情况只会影响按需加载模块,所以所有内容全部被打包到一起了。

1.2.5 有模块动态导入

这里 lodash 使用动态导入,打包结果中可以看到 lodash 被单独打包了,因为默认情况下异步模块会被单独打包。

1.2.6 react 按需加载

打包结果分析:生成了三个 JS 文件,index.js Hello.js 和lodash。

Hello.js 是异步引入的,单独打包,因为默认情况下 webpack 会对异步模块进行打包优化。

lodash 符合提到默认的 4 个条件,所以 lodash 也被单独打包了。

1.2.7 lodash 按需加载

我们调整下 lodash 的引入,只引入 sum 模块。

可以看到此时就两个文件,因为 lodash/sum 的文件大小小于 20kb,不会被单独打包。

import {sum} from 'lodash-es'; 同理也是打印俩文件;

1.2.8 共享模块打包

除了 node_modules 满足条件会被单独打包,共享模块也会,我们看下面例子:

为啥共享模块和第三方库是分开打包的,是和 webpack 的默认配置有关,后面我们就可以看到默认配置。

1.2.9 初始和异步模块的公共库

相比于1.2.8,加了两行,可以看到lodash打包到初始块文件里了,异步模块和初始块都有的第三方库,会被打包在初始模块中。原因也很简单,Hello.js和World.js 加载前肯定会加载 index 模块,index 模块中有了 lodash,Hello.js和World.js 就直接可以使用 index 模块中的 lodash 了。讲完了 webpack 默认情况下对打包块的优化,接下来看 splitChunks 配置项。

1.2.10 配置项

默认配置

webpack 5 splitChunks 默认配置如下,上面提到的默认情况下打包的条件(按需加载 + 满足 4 个默认打包条件)在下方配置中就可以体现。

module.exports = {
  //...optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 20000,
      minRemainingSize: 0,
      minChunks: 1,
      maxAsyncRequests: 30,
      maxInitialRequests: 30,
      enforceSizeThreshold: 50000,
      cacheGroups: {
        defaultVendors: {
          test: /[/]node_modules[/]/,
          priority: -10,
          reuseExistingChunk: true,
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    },
  },
};
  • chunks: 表示哪些代码需要优化,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),默认为 async

  • minSize: 表示在压缩前的最小模块大小,默认为 20000Bytes.

  • minChunks: 表示被引用次数,默认为 1

  • maxAsyncRequests: 按需加载时候最大的并行请求数,默认为 30

  • maxInitialRequests: 一个入口最大的并行请求数,默认为 30

  • enforceSizeThreshold:强制执行拆分的体积阈值

  • cacheGroups: 缓存组。缓存组的属性除上面所有属性外,还有 test, priority, reuseExistingChunk

    • test: 用于控制哪些模块被这个缓存组匹配到
    • priority: 缓存组打包的先后优先级
    • reuseExistingChunk: 如果当前代码块包含的模块已经有了,就不在产生一个新的代码块
    • 自定义打包块的默认优先级是 0,所有优先处理自定义打包。

1.2.11 提取第三方库

最后看下之前 CommonsChunkPlugin 常用的分离部分第三方库功能。

上面已经提到了设置 chunks: initial || all 都可以提取出第三方库。但是它是把所有第三库提取出来,所以我们在只提取 react 和 react-dom 的情况下,需要自定义一个 cacheGroup。


splitChunks: {
    chunks: 'all',
    cacheGroups: {
      react: {
          name: 'react',
          test: /[\/]node_modules[\/](react|react-dom)[\/]/,
      }
    }
}

可以看到我们新增了一个缓存组,只匹配 react 和 react-dom,所以达到了之前 CommonsChunkPlugin 的功能。

1.2.12 optimization.runtimeChunk

最后提一下 runtimeChunk,通过optimization.runtimeChunk: true选项,webpack 会添加一个只包含运行时 (runtime) 额外代码块到每一个入口。(译注:这个需要看场景使用,会导致每个入口都加载多一份运行时代码)

1.3 总结

webpack5 默认情况下只对异步模块做打包优化,额外的打包必须满足 4 个条件(webpack 的默认配置,可修改)。根据需求可调整为只对初始模块做打包优化,或者初始和异步模块一起优化。同时可配置自己的打包规则。

简而言之:chunks 控制打包作用范围,其他控制打包规则。

webpack5 的 splitChunks 功能是比较强大的,不过推荐还是使用默认模式,或者提取一下第三方库。

参考:webpack5 SplitChunksPlugin 实用指南 - 掘金