缓存是常用的性能优化手段之一,其本质是空间换时间。(缓存属于延后优化策略,当然也可以提前优化,比如预加载)
在webpack4时代需要借助loader和plugin来实现本地缓存(就是将构建产物暂存在本地,如果没有更新则复用构建结果)。在v5时代,webpack已经内置了缓存相关的配置。
其基本逻辑是:在首次构建完毕后将 Module、Chunk、ModuleGraph 三类对象的状态序列化并记录到缓存文件中;在下次构建开始时,尝试读入并恢复这些对象的状态,从而跳过执行 Loader 链、解析 AST、解析依赖等耗时操作,从而提升编译性能。
v5的cache配置
webpack5开启本地缓存的配置方式非常简单:
module.exports = {
//...
cache: {
type: 'filesystem'
},
//...
};
就上面这三行代码,就能开启本地化缓存了。
当然,webpack还提供了其他配置:
- cache.type:缓存类型,支持 ‘memory’ | ‘filesystem’,需要设置为 filesystem 才能开启持久缓存;
- cache.cacheDirectory:缓存文件路径,默认为 node_modules/.cache/webpack ,最终的缓存目标是 cache.cacheDirectory + cache.name 的混合;
- cache.maxAge:失效时间,默认值为 5184000000
- cache.buildDependencies:额外的依赖文件,当这些文件内容发生变化时,缓存会完全失效而执行完整的编译构建,通常可设置为各种配置文件;
- cache.profile:是否输出缓存处理过程的详细日志,默认为 false
v4时代的缓存
在webpack4时代,本地持久化缓存的能力还没有集成进webpack,所以想要使用缓存可以通过:
hard-source-webpack-plugin、 cache-loader,以及loader自带的缓存能力,比如babel-loader;
hard-source-webpack-plugin
hard-source-webpack-plugin 实现的缓存效果和webpack5自带的效果差不多,缓存的比较全面(不仅仅缓存了 Loader 运行结果,还保存了 Webpack 构建过程中许多中间数据,包括:模块、模块关系、模块 Resolve 结果、Chunks、Assets 等)。
yarn add -D hard-source-webpack-plugin
const HardSourceWebpackPlugin = require("hard-source-webpack-plugin");
module.exports = {
// ...
plugins: [
new HardSourceWebpackPlugin(),
],
};
cache-loader
cache-loader 也很常用,但只缓存了 Loader 执行结果,整体效果不如 Webpack5 内置的缓存功能。
module.exports = {
// ...
module: {
rules: [{
test: /\.js$/,
use: ['cache-loader', 'babel-loader', 'eslint-loader']
}]
},
// ...
};
cache-loader 还提供了一系列控制缓存逻辑的配置属性,特别是 read/write 可以用于改变缓存数据的持久化逻辑,借助这两个属性我们甚至能够实现多台机器间的缓存共享。
const redis = require("redis");
const client = redis.createClient();
// 读数据
async function read(key, callback) {
// ...
const result = await client.get(key);
const data = JSON.parse(result);
callback(null, data);
}
// 写数据
async function write(key, data, callback) {
// ...
await client.set(key, JSON.stringify(data));
callback();
}
module.exports = {
// ...
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: "cache-loader",
// 传入 read、write 函数
options: { read, write },
},
"babel-loader",
],
},
],
},
};
webpack组件自带的缓存功能
一些webpack的插件或者loader也提供的有缓存功能,常用的有:
babel-loader: 设置 cacheDirectory = true 即可开启缓存功能,默认情况下,缓存内容会被保存到 node_modules/.cache/babel-loader 目录,你也可以通过 cacheDirectory = ‘dir’ 属性设置缓存路径
module.exports = {
// ...
module: {
rules: [{
test: /\.m?js$/,
loader: 'babel-loader',
options: {
cacheDirectory: true,
},
}]
},
// ...
};
ESLint:eslint-loader/eslint-webpack-plugin,设置 cache = true
module.exports = {
plugins: [
new ESLintPlugin({ cache: true }),
],
};
Stylelint:stylelint-webpack-plugin设置 cache = true
module.exports = {
plugins: [
new StylelintPlugin({ files: '**/*.css', cache: true }),
],
};