[关闭]
@Dale-Lin 2022-09-09T12:01:29.000000Z 字数 2246 阅读 588

Webpack 持久化缓存提升构建性能

webpack5


Webpack5 提供了持久化缓存的用法(Webpack4 借助第三方 loader/Plugin 实现),能将首次构建的过程和结果数据保存到本地 fs,在下次执行构建时跳过解析、链接、编译等一系列非常消耗性能的操作,直接复用上次的 Module/ModuleGraph/Chunk 数据,迅速构建出 bundle。

配置

原理

Webpack5 会将首次构建出的 Module/ModuleGraph/Chunk 等对象序列化后保存到硬盘中,二次编译可以复用缓存数据。

从构建步骤来看,webpack 构建过程可以分成三个阶段:

过程中存在许多 cpu 密集型操作,例如调用 Loader 链加载文件时,遇到 babel-loader、eslint-loader、ts-loader 等工具时可能需要重复生成 AST;分析模块依赖时需要遍历 AST 执行大量运算;Seal 阶段也存在大量 AST 遍历、代码转换、优化等。

Webpack5 的持久化缓存功能将 Module、Chunk、ModuleGraph 三类产物的状态序列化后保存到 fs 中,在下次编译时对比每一个文件的 contentHash 和 timestamp(timestamp 可以监听文件移动),未发生变化的文件跳过编译而直接使用缓存副本;发生变更的模块重新执行编译流程。

生成阶段完成后产生缓存;可以使用缓存的文件跳过构建阶段,即 初始化 -> 生成阶段 -> 写出;

Webpack4 使用 cache-loader

webpack4 及之前版本只能通过第三方组件实现,包括:

cache-loader

cache-loader 将 Loader 处理结果保存到硬盘,下次运行时,若文件内容没有变化则直接返回缓存结果:

  1. yarn add -D cache

必须将 cache-loader 放在 loader 数组首位

  1. module.exports = {
  2. // ...
  3. modules: {
  4. rules: [{
  5. test: /\.js$/,
  6. use: [
  7. 'cache-loader',
  8. 'babel-loader',
  9. 'eslint-loader'
  10. ]
  11. }]
  12. }
  13. }

cache-loader 只缓存了 Loader 执行结果,缓存范围和精度不如 Webpack5 内置缓存

Webpack4 使用 hard-source-webpack-plugin

hard-source-webpack-plugin 也是实现一种缓存功能的第三方组件,不仅缓存了 Loader 运行结果,还保存了 Webpack 构建过程中许多中间数据,包括:模块、模块关系、模块 Resolve 结果、chunk、assets 等,效果几乎与 webpack5 自带的 Cache 对齐:

  1. yarn add -D hard-source-webpack-plugin
  1. const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
  2. module.exports = {
  3. // ...
  4. plugins: [
  5. new HardSourceWebpackPlugin(),
  6. ]
  7. }

首次运行时,hard-source-webpack-plugin 会在 node_modules/.cache 写入一系列的日志文件,在下次运行时复用记录的数据,跳过一系列构建步骤。

hard-source-webpack-plugin 的底层逻辑和 webpack5 的持久化缓存相似,但优化效果稍微差一些;

Webpack 生态组件自带的缓存功能

除了上述方案,还可以使用 webpack 组件自带的缓存能力来提升特定领域的编译性能,这一类组件有:

babel-loader

开启 cacheDirectory = true 即可:

  1. module.exports = {
  2. // ...
  3. module: {
  4. rules: [{
  5. test: /\.js$/,
  6. loader: 'babel-loader',
  7. options: {
  8. cacheDirectory: true
  9. }
  10. }]
  11. }
  12. }

默认情况下,缓存内容会被保存到 node_modules/.cache/babel-loader 目录,也可通过 cacheDirectory = ${dir} 来设置缓存路径。

eslint-webpack-plugin

设置 options.cachetrue,会把 lint 的结果进行缓存到 .eslintcache 目录下;可以使用 options.cacheLocation 设置缓存路径。

stylelint-webpack-plugin

设置 cache: true 会把 lint 结果缓存到 process.cwd()./.stylelintcache 目录下。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注