webpack5 持久化缓存
webpack5 持久化缓存
背景
- 为什么 react 新项目启动这么快?如
- linhuibaEnterExit 进撤场
- resource-service-web 资源服务
- 为什么有时候修改代码、升级依赖不生效
原因
开启了 webpack5 的新特性-持久化缓存。
缓存文件至 node_modules/.cache
,如果需要清除缓存,删除该文件。
项目内的 cache 的配置
webpack5 默认不开启,项目内的脚手架内部配置了开启,配置如下
- linhuibaEnterExit 进撤场项目
cache: {
type: 'filesystem',
version: '75976c3e8e6750af72d5fdc2c8f5f52d',
cacheDirectory: 'xx/linhuibaEnterExit/node_modules/.cache',
store: 'pack',
buildDependencies: {
defaultWebpack: [ 'webpack/lib/' ],
config: [
'xx/linhuibaEnterExit/node_modules/react-scripts/config/webpack.config.js'
],
tsconfig: [ 'xx/linhuibaEnterExit/tsconfig.json' ]
}
}
- resource-service-web 资源服务
cache: {
type: 'filesystem',
version: '56e655ab29e15739b04e5da711108e4f',
cacheDirectory: 'xx/resource-service-web/node_modules/.cache',
store: 'pack',
buildDependencies: {
defaultWebpack: ['webpack/lib/'],
config: [
'xx/resource-service-web/node_modules/react-scripts/config/webpack.config.js'
],
tsconfig: ['xx/resource-service-web/tsconfig.json']
}
}
内存缓存和文件缓存
- memory 内存缓存 webpack4 的缓存是内存缓存,即将构建结果缓存到内存中,当进行热更新时,从内容中读取缓存,所以响应速度快;但是每次项目重新启动时,就需要在内容重新创建缓存。
- filesystem 文件缓存(持久化缓存) webpack5 可以将构建结果持久化缓存到本地的磁盘,二次构建(非 watch 模块)直接利用磁盘缓存的结果从而跳过构建过程当中的 resolve、build 等耗时的流程,从而大大提升编译构建的效率。
持久化缓存
持久化缓存主要解决的就是优化编译流程,减少编译耗时的问题,通过全新的缓存系统的设计使得整个构建流程更加的高效和安全。
默认情况下不启用持久缓存,必须选择使用。(因为 webpack 希望用户了解这个功能开启后带来的优缺点,再自行决策是否开启。)
因为 webpack 试图将安全性置于性能之上。我们不希望默认启用一项功能,该功能会将您的性能提高 95%,但会破坏您的应用程序/工作流程/构建 5%。
缓存失效
比如 某个缓存的目标文件(如 magic.js)进行了修改,webpack 需要匹配到 magic.js ,识别存在差异,然后将缓存文件失效,再重建缓存;但也有可能匹配失败,此时就需要人为进行干预了。这部分就属于 5%。
webpack 还可能存在缓存失效的场景:
- 当 npm 升级加载器或插件时
- 当更改配置时
- 当更改正在配置中读取的文件时
- 当 npm 升级配置中使用的依赖项时
- 当将不同的命令行参数传递给构建脚本时
- 当有自定义构建脚本并更改它时
构建依赖项、版本和名称
为了处理构建的这些“依赖关系”,webpack 提供了三个新工具:
- cache.buildDependencies 构建依赖
cache.buildDependencies: {
defaultWebpack: ["webpack/lib/"]
}
cache.buildDependencies: {
config: [__filename]
}
- cache.version 版本,传递不同的字符串将使持久缓存失效
cache: {
version: `${process.env.GIT_REV}`
}
- cache.name 名称,用作持久换成文件的文件名,如
--env.target mobile|desktop
参数为移动或桌面用户创建构建
cache: {
name: `${env.target}`
}
快照类型
和持久化缓存另外一个相关的配置是:snapshot
。
snapshot 相关的配置决定了缓存内存生成 snapshot 时所采用的策略(timestamps | content hash | timestamps + content hash),而这个策略最终会影响到缓存是否失效,即 webpack 是否决定来使用缓存。
const path = require('path')
module.exports = {
// ...
snapshot: {
// 针对包管理器维护存放的路径,如果相关依赖命中了这些路径,那么他们在创建 snapshot 的过程当中不会将 timestamps、content hash 作为 snapshot 的创建方法,而是 package 的 name + version
// 一般为了性能方面的考虑,
managedPaths: [path.resolve(__dirname, '../node_modules')],
immutablePaths: [],
// 对于 buildDependencies snapshot 的创建方式
buildDependencies: {
// hash: true
timestamp: true
},
// 针对 module build 创建 snapshot 的方式
module: {
// hash: true
timestamp: true
},
// 在 resolve request 的时候创建 snapshot 的方式
resolve: {
// hash: true
timestamp: true
},
// 在 resolve buildDependencies 的时候创建 snapshot 的方式
resolveBuildDependencies: {
// hash: true
timestamp: true
}
}
}
webpack4 持久化缓存
webpack4 可使用 hard-source-webpack-plugin,它就是基于上述 wbpack5 的实现思路的一个插件。
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin'); // 编译缓存
// 如果无法编译,删除 node_modules/.cache 文件夹
webpackConfig.plugins.push(new HardSourceWebpackPlugin({
configHash: 'development',
}));