logo学习随笔

webpack 内联 runtimeChunk 至index.html

October 13, 2020

背景

最近在公司做移动端项目优化的工作,目前主要的重心放在了打包体积优化上。目前项目中采用了 webpack 4,实际上已经为我们提供了诸多方便的配置能力进行打包优化。

抽离 webpack 运行时代码

将 optimization.runtimeChunk 设置为 true 或 ‘multiple’,会为每个只含有 runtime 的入口添加一个额外 chunk。此配置的别名如下:

webpack.config.js

module.exports = {
  //...
  optimization: {
    runtimeChunk: {
      name: entrypoint => `runtime~${entrypoint.name}`,
    },
  },
};

值 “single” 会创建一个在所有生成 chunk 之间共享的运行时文件。此设置是如下设置的别名:

webpack.config.js

module.exports = {
  //...
  optimization: {
    runtimeChunk: {
      name: 'runtime',
    },
  },
};

通过将 optimization.runtimeChunk 设置为 object,对象中可以设置只有 name 属性,其中属性值可以是名称或者返回名称的函数, 用于为 runtime chunks 命名。

默认值是 false:每个入口 chunk 中直接嵌入 runtime。

内联

将运行时代码剥离的优势是,不需要在每个 chunk 中都打包运行时代码。结合 HtmlWebpackPlugin 的 chunks 属性可以将 runtimeChunk 以 script 标签的形式引入,不过会多发一次请求,更推荐的做法是将 runtimeChunk 打包至 index.html 中。

create-react-app 中的子包 react-dev-utils 中提供了一些 webpack 插件,其中 InlineChunkHtmlPlugin 就可以满足上述的需求:

webpack.config.js

var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');

// webpack config
var publicUrl = '/my-custom-url';

module.exports = {
  output: {
    // ...
    publicPath: publicUrl + '/',
  },
  // ...
  plugins: [
    // Generates an `index.html` file with the <script> injected.
    new HtmlWebpackPlugin({
      inject: true,
      template: path.resolve('public/index.html'),
    }),
    // Inlines chunks with `runtime` in the name
    new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime/]),
    // ...
  ],
  // ...
};

注意: HtmlWebpackPlugin 和 InlineChunkHtmlPlugin 需要串联使用,并且需要 HtmlWebpackPlugin >= 4.x 版本。