webpack 中的 optimization
本文最后更新于:2022年4月22日 上午
webpack 中可以通过对 optimization 配置来对我们项目进行一些优化
1. 不单独生成注释信息 (optimization.minimizer)
假设我们现在 webpack 配置文件如下
webpack.config.jsconst path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  mode:'production',
  entry: {
    index: "./src/index.js",
  },
  output: {
    filename: "[name].bundle.js",
    path: path.resolve("./build"),
    chunkFilename: '[name].[hash:6].chunk.js'
  }, 
  module: {
    rules: [
      {
        test: /\.jsx?$/i,
        use: "babel-loader",
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./public/index.html",
    }),
  ],
};
src/index.jsimport _ from 'lodash';
console.log(_.join(['hello','webpack5','index.js']));现在我们运行打包命令,可以看到打包之后的代码现在是这样的,它除了帮我们打包 index.js 外,还帮我们生成了一个 index.bunle.js.LICENSE.txt,这个文件是一些许可证注释信息,
试想一下,当我们项目越来越大时,我们肯定是不希望它给我们生成一堆这样的注释文件的,那这个时候我们就可以在 optimization.minimizer 来进行配置
minimizer 可以配置很多个 TerserPlugin 插件实例 , 通过手动配置来覆盖默认的压缩工具
TerserPlugin 插件在 webpack5 中已经内置了,如果使用的 webpack5 以下的版本,则需要手动安装一下
重新修改 webpack 的配置文件
extractComments 是用来配置是否单独生成注释文,有关 extractComments 的更多配置,可以查看 这里
webpack.config.jsconst TerserPlugin = require("terser-webpack-plugin");
...
optimization: {
  minimizer: [ new TerserPlugin({ extractComments: false }) ],
}
...重新执行打包命令,可以看到以下目录,已经没有帮我们单独生成注释文件了
2. 配置 模块id 生成的算法 (optimization.chunkIds)
不知道有没有朋友注意到,当我们使用 @vue/cli 来搭建我们的项目的时候,当我们把项目跑起来后,可以看到很多类似 1.js 2.js 3.js 这种文件,这种文件是怎么生成的呢
我们可以通过配置 optimization.chunkIds 来修改模块 id 生成的算法,如果我们将 optimization.chunkIds 修改为 named 后的话,我们在开发阶段就可以看到生成的 js 文件拼接上了我们的原文件名
| 选项值 | 描述 | 
|---|---|
natural | 
按使用顺序的数字 id | 
named | 
对调试更友好的可读的 id,会拼接上模块的原文件名 | 
deterministic | 
在不同的编译中不变的短数字 id,有益于长期缓存,在生产模式中会默认开启 | 
size | 
专注于让初始下载包大小更小的数字 id | 
total-size | 
专注于让总下载包大小更小的数字 id | 
2.1 多入口文件时注意点 (optimization.runtimeChunk)
当我们的项目有多个入口文件时,可能我们多个入口文件都同时依赖了相同的第三方库,这样的话,在有些情况下,有可能这个库会被同时被实例化多次,这种情况我们肯定是不希望发生的,那么我们就可以通过配置 optimization.runtimeChunk 来生成一个所有 chunk 之前共享的 运行时文件
这里 有更多关于多入口文件项目依赖的注意点
optimization.runtimeChunk 默认的值是 false 
false会将所有的入口文件的 runtime 运行时文件写入到打包后的文件中'single'会生成一个在 所有 chunk 间共享的一个运行时文件'multiple'或者true会为所有的入口 chunk 都单独生成一个runtime运行时文件
webpack.common.jsconst path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  mode:'production',
  entry: {
    index: "./src/index.js",
  },
  output: {
    filename: "[name].bundle.js",
    path: path.resolve("./build"),
    chunkFilename: '[name].[hash:6].chunk.js'
  }, 
  module: {
    rules: [
      {
        test: /\.jsx?$/i,
        use: "babel-loader",
      },
    ],
  },
  optimization: {
    minimizer: [ new TerserPlugin({ extractComments: false }) ],
    chunkIds: 'named',
    // 只会生成一个 runtime 运行时文件
    runtimeChunk: 'single',
  
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./public/index.html",
    }),
  ],
};2.1.1 为每个入口文件都单独配置 runtime 运行时文件
首先将 optimization 中的 runtimeChunk 修改为 'multiple' 或 true.
webpack.common.js...
optimization: {
  ...
  runtimeChunk: 'multiple',
}
...然后重新执行打包命令,可以看到会生成以下文件,webpack 为我们给每个入口文件都生成了 runtime 运行时文件
2.2.2 为所有入口文件只生成一个 runtime 运行时文件
首先将 optimization 中的 runtimeChunk 修改为 'single'.
webpack.common.js...
optimization: {
  ...
  runtimeChunk: 'single',
}
...然后重新执行打包命令,可以看到会生成以下文件,webpack 只为我们生成了一个 runtime 运行时文件
有关
optimization.runtimeChunk的更多信息,可以查看 此处
3. optimization.splitChunks
是用来 配置 webpack 中模块分块策略的
以下是 splitChunksPlugin 的默认值
webpack.config.jsoptimization: {
    splitChunks: {
      // 'async'  'initial'  'all'  
      // async 为只有异步引入模块时才会单独打包
      // all   为所有的模块都单独打包成一个文件
      chunks: 'async',
      // 打包成 chunk 后最小的大小,单位为字节
      minSize: 20000,
      minRemainingSize: 0,
      
      // 将大于 maxSize 的 chunk 分割成一个个较小的 chunk ,且分割后的 chunk 最小体积为 minSize 
      maxSize: 0,
      // 当模块被引用过几次后将其单独打包成一个 chunk
      minChunks: 1,
      // 按需加载时的最大并行请求数
      maxAsyncRequests: 30,
      // 入口的最大并行请求数。
      maxInitialRequests: 30,
      // 强制执行拆分的大小阈值
      enforceSizeThreshold: 50000,
      // 缓存组中可以单独配置以上的所有配置,
      // 除此之外新增了 test 、 priority 和 reuseExistingChunk 三个属性
      // test 填写 模块路径或者 chunk 名称来做匹配到的资源
      // priority 配置该缓存组的优先级,默认值为0,该值优先级为负数,所以我们通常设置为负数,
      // 当匹配到的资源属于多个缓存组的时候,就会根据 优先级来选择最终的匹配自定义缓存组
      // reuseExistingChunk 如果当前 chunk 包含 其它从主 chunk 中拆分出来的模块,则它们会被复用
      cacheGroups: {
        defaultVendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          reuseExistingChunk: true,
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    },
  }本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处。