缓存优化

缓存优化的基本原理

Webpack 4 内置了压缩插件 TerserWebpackPlugin,且默认开启了缓存参数。在初次构建的压缩代码过程中,就将这⼀阶段的结果写⼊了缓存⽬录 (node_modules/.cache/terser-webpack-plugin/)中,当再次构建进⾏到压缩代码阶段时,即可对⽐读取已有缓存。

编译阶段的缓存优化

编译过程的耗时点主要在使⽤不同加载器(Loader)来编译模块的过程。

  1. Babel-loader
    Babel-loader 是绝⼤部分项⽬中会使⽤到的 JS/JSX/TS 编译器。在 Babel-loader 中,与缓存相关的设置主要有:

    • cacheDirectory:默认为 false,即不开启缓存。当值为 true 时开启缓存并使⽤默认缓存⽬录(./node_modules/.cache/babel-loader/),也可以指定其他路径值作为缓存⽬录。
    • cacheIdentifier:⽤于计算缓存标识符。默认使⽤ Babel 相关依赖包的版本、babelrc 配置⽂件的内容,以及环境变量等与模块内容⼀起参与计算缓存标识符。如果上述内容发⽣变化,即使模块内容不变,也不能命中缓存。
    • cacheCompression:默认为 true,将缓存内容压缩为 gz 包以减⼩缓存⽬录的体积。在设为 false 的情况下将跳过压缩和解压的过程,从⽽提升这⼀阶段的速度。
  2. Cache-loader
    在编译过程中利⽤缓存的第⼆种⽅式是使⽤ Cache-loader。在使⽤时,需要将 cache-loader 添加到对构建效率影响较⼤的 Loader(如 babel-loader 等)之前。
    执⾏两次构建后可以发现,使⽤ cache-loader 后,⽐使⽤ babel-loader 的开启缓存选项后的构建时间更短。主要原因是 babel-loader 中的缓存信息较少,⽽ cache-loader 中存储的 Buffer 形式的数据处理效率更⾼。

优化打包阶段的缓存优化

  1. ⽣成 ChunkAsset 时的缓存优化
    在 Webpack 4 中,⽣成 ChunkAsset 过程中的缓存优化是受限制的:只有在 watch 模式下,且配置中开启 cache 时(development 模式下⾃动开启)才能在这⼀阶段执⾏缓存的逻辑。这是因为,在 Webpack 4 中,缓存插件是基于内存的,只有在 watch 模式下才能在内存中获取到相应的缓存数据对象。

  2. 代码压缩时的缓存优化
    在代码压缩阶段,对于 JS 的压缩,TerserWebpackPlugin 和 UglifyJSPlugin 都是⽀持缓存设置的。⽽对于 CSS 的压缩,⽬前最新发布的 CSSMinimizerWebpackPlugin ⽀持且默认开启缓存,其他的插件如 OptimizeCSSAssetsPlugin 和 OptimizeCSSNanoPlugin ⽬前还不⽀持使⽤缓存。

缓存的失效

如何最⼤程度地让缓存命中,成为我们选择缓存⽅案后⾸先要考虑的事情。

  1. 缓存标识符发⽣变化导致的缓存失效
    通常情况下我们需要尽可能少地变更会影响到缓存标识符⽣成的字段。

  2. 编译阶段的缓存失效
    编译阶段的执⾏时间由每个模块的编译时间相加⽽成。在开启缓存的情况下,代码发⽣变化的模块将被重新编译,但不影响它所依赖的及依赖它的其他模块,其他模块将继续使⽤缓存。因此,这⼀阶段不需要考虑缓存失效扩⼤化的问题。

  3. 优化打包阶段的缓存失效
    优化打包阶段的缓存失效问题则需要引起注意。
    尽可能地把那些不变的处理成本⾼昂的模块打⼊单独的 Chunk 中。这就涉及了 Webpack 中的分包配置——splitChunks。

  4. 使⽤ splitChunks 优化缓存利⽤率
    构建分包的好处有许多,⽐如合并通⽤依赖、提升构建缓存利⽤率、提升资源访问的缓存利⽤率、资源懒加载等。

其他使⽤缓存的注意事项

  1. CI/CD 中的缓存⽬录问题

  2. 缓存的清理

  3. 与产物的持久化缓存相区别

你可能感兴趣的:(缓存优化)