当 Webpack 在输出 bundle 文件的时候,它同时还维护了一个运行时。这个运行时包含一个要加载的文件的清单。当文件内容发生变化的时候,这个文件清单也会发生变化,因此我们需要将这个运行时也单独输出到独立的文件中。

导出运行时文件

Bundle Spliting 一章中我们已经交代了巨大部分输出 bundle 的配置,这里我们需要通过 optimization.runtimeChunk 来输出运行时。

webpack.config.js

const productionConfig = merge([
  ...
  // { optimization: { splitChunks: { chunks: "all" } } },
  {
    optimization: {
      splitChunks: { chunks: "all" },
      runtimeChunk: { name: "runtime" },
    },
  },
  ...
]);
1
2
3
4
5
6
7
8
9
10
11

runtime 这个名称是默认值,我们可以指定任何其他的名称。

此时执行 npm run build,可以看到输出结果为:

⬡ webpack: Build Finished
⬡ webpack: assets by path *.js 130 KiB
    asset 935.a25ff4285adcf5d835fd.js 126 KiB [emitted] [immutable] [minimized] (id hint: vendors) 2 related assets
    asset runtime.73d14ef014bf8bb2c12f.js 3.12 KiB [emitted] [immutable] [minimized] (name: runtime) 1 related asset
    asset main.be57b34b7c7a29bc1280.js 479 bytes [emitted] [immutable] [minimized] (name: main) 1 related asset
    asset 958.1752e720e564a63a9d5f.js 204 bytes [emitted] [immutable] [minimized] 1 related asset
  asset main.dd02bdb46b234aa6a450.css 1.37 KiB [emitted] [immutable] [minimized] (name: main)
  asset index.html 377 bytes [emitted]
  Entrypoint main 131 KiB (182 KiB) = runtime.73d14ef014bf8bb2c12f.js 3.12 KiB 935.a25ff4285adcf5d835fd.js 126 KiB main.dd02bdb46b234aa6a450.css 1.37 KiB main.be57b34b7c7a29bc1280.js 479 bytes 3 auxiliary assets
  runtime modules 7.95 KiB 10 modules
  orphan modules 465 bytes [orphan] 2 modules
  code generated modules 133 KiB (javascript) 4.18 MiB (css/mini-extract) [code generated]
    modules by path ./node_modules/ 133 KiB
      modules by path ./node_modules/react/ 6.48 KiB 2 modules
      modules by path ./node_modules/react-dom/ 119 KiB 2 modules
      modules by path ./node_modules/scheduler/ 4.91 KiB
        ./node_modules/scheduler/index.js 198 bytes [built] [code generated]
        ./node_modules/scheduler/cjs/scheduler.production.min.js 4.72 KiB [built] [code generated]
      ./node_modules/object-assign/index.js 2.06 KiB [built] [code generated]
    modules by path ./src/ 633 bytes (javascript) 4.18 MiB (css/mini-extract)
      ./src/index.js + 2 modules 600 bytes [built] [code generated]
      css ./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[0].use[2]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[0].use[3]!./src/main.css 4.18 MiB [code generated]
      ./src/lazy.js 33 bytes [built] [code generated]
  webpack 5.11.1 compiled successfully in 20891 ms
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

根据上面的配置,运行时被输出到了 runtime 这个文件中。因为我们使用了 MiniHtmlWebpackPlugin 这个插件,它会自动将运行时文件更新到 html 中,无需我们手动处理。

从 Webpack 5 开始,会根据项目的 .browserslist 文件定义的浏览器信息和 target 来输出运行时文件。如果 target 设置的 es5,则会输出一个兼容 ECMAScript 5 的文件,如果设置的是 es2015 则会输出使用较新语法的文件。

使用构建历史(records)

在前面章节中提到 AggressiveSplittingPlugin,这个插件会使用 record 来做缓存,从而加快构建性能。

record 用来缓存不同构建之间的模块 id 的。我们使用 records.json 这个文件来保存模块 id。

webpack.config.js


const path = require('path');
...
const productionConfig = merge([
  ...
  { recordsPath: path.join(__dirname, "records.json") },
]);
1
2
3
4
5
6
7

此时执行 npm run build,可以看到在项目跟目录下多了一个 records.json 文件,下次 Webpack 在构建的时候会读取这个文件。

recordsInputPathrecordsOutputPath 提供了更加细粒度的控制。

与其他工具集成

有时候我们需要将输出资源与其他工具集成。webpack-manifest-pluginopen in new windowwebpack-assets-manifestopen in new window 可以提供一些帮助。这两个插件都输出一个 JSON 文件,里面包含文件路径的映射关系。

总结

Webpack 构件过程中有一个运行时,这个运行时包含了运行应用的启动信息。

一些插件可以帮助我们将运行时更新到 index.html 中,同时还可以输出 JSON 信息,这在服务端渲染等场景下非常有用。

构建记录 record 可以缓存不同次构建间的模块 ID 信息。缺点是我们需要额外存储这个文件。

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