如何优化Webpack的构建速度

9/1/2021 Webpack

要优化 Webpack 的构建速度,首先需要了解 Webpack 的运行流程和顺序。然后,根据实际项目进行分析和优化,逐步提高项目的构建速度。

Webpack 的运行流程主要分为以下步骤:

  1. 初始化参数:合并项目的配置文件和命令行参数,得出最终的参数。
  2. 开始编译:通过参数初始化 Compiler 对象,执行 run 来开始编译。
  3. 确定入口:在配置的 entry 参数中找到入口文件。
  4. 编译模块:从入口文件开始寻找出所有依赖的文件,并使用 loader 对这些文件进行编译。
  5. 完成模块编译:编译结束后,可以得到最终内容和文件之间的依赖关系。
  6. 确定输出资源:将编译完成的模块组装成一个个 chunk,并建立好引用关系,加入到输出列表中。
  7. 输出文件:将输出列表中的文件输出到文件系统中。

在以上步骤中,影响打包速度并可以进行优化的主要是第三和第四步。以下是一些优化因素:

# 优化文件和模块的查找时间

  1. 使用oneOf配置在 loader 中,表示找到一个合适的 loader 就不用继续寻找剩下的 loader。
  2. 在 loader 的配置中,使用test来匹配对应的文件,以及includeexclude来确定文件集。
  3. 配置resolve 参数 (opens new window)中的:
    • module:指定目录中查找第三方模块。
    • alias:将原导入路径映射为新的导入路径。
    • extensions:指定文件后缀,以便在项目中查找关联的文件。
    • mainFields:指定不同环境的入口文件。

# 优化 loader 的编译时间

使用thread-loader是官方推荐的方法,将其放在需要优化的文件配置的最前面。这将使这类文件的编译在一个 worker 池中运行,但每个 worker 需要一定时间(600ms)进行预热,因此请在需要耗时的编译中使用。

rules: [
  {
    test: /\\.js$/,
    exclude: /node_modules/,
    use: ['thread-loader', 'babel-loader'],
  },
];

# 优化文件压缩的时间

默认情况下,Webpack 使用terser-webpack-plugin插件来压缩优化 JavaScript 代码,该插件使用 terser 来缩小 JavaScript 并开启多进程。您也可以使用esBuild来极大加快编译时间。

module.exports = {
  optimization: {
    minimizer: [
      new TerserPlugin({
        parallel: true,
      }),
    ],
  },
};

# 优化开发过程中的二次打包时间

在开发阶段,合理使用缓存可以显著减少二次编译的时间:

  1. 开启babel-loadercacheDirectory标志。
  2. 使用cache-loader,将其放在需要优化的编译最前面。这将使缓存结果保存到磁盘中。
  3. 使用HardSourceWebpackPlugin(Webpack 5 已内置),第一次构建时间正常,第二次将大大提高速度。
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const clientWebpackConfig = {
  // ...
  plugins: [
    new HardSourceWebpackPlugin({
      cacheDirectory: path.join(
        __dirname,
        './lib/.cache/hard-source/[confighash]'
      ),
      configHash: function (webpackConfig) {
        return require('node-object-hash')({ sort: false }).hash(webpackConfig);
      },
      environmentHash: {
        root: process.cwd(),
        directories: [],
        files: ['package-lock.json', 'yarn.lock'],
      },
      cachePrune: {
        maxAge: 2 * 24 * 60 * 60 * 1000,
        sizeThreshold: 50 * 1024 * 1024,
      },
    }),
    new HardSourceWebpackPlugin.ExcludeModulePlugin([
      {
        test: /.*\\.DS_Store/,
      },
    ]),
  ],
};

# 分析工具

使用以下分析工具来确定优化方案:

  1. speed-measure-webpack-plugin
  2. webpack-bundle-analyzer
  3. 在线工具如Webpack AnalyseWebpack VisualizerWebpack bundle optimize helper(部分工具已不再维护)

使用这些工具可以更好地了解 Webpack 的构建性能,并找到需要优化的瓶颈。