Cache 缓存机制
约 1134 字大约 4 分钟
2025-03-15
一、简介
Webpack 的缓存机制是一个强大的功能,旨在提高构建速度和性能。
具体来说,分为两类:
内存缓存:目的是提高开发和构建的速度。
- 缓存数据存储在内存中,适用于开发环境,可以快速访问但重启后会丢失;
- 主要通过 Webpack Dev Server 的内存文件系统和模块热替换等功能来实现;
文件系统缓存:目的是让浏览器能够有效地缓存资源,减少重复下载。
- 缓存数据存储在磁盘上,适用于开发环境和生产环境,可以持久化缓存数据;
- 主要通过生成带有内容哈希的文件名和配置服务器端的
Cache-Control
头来实现; - 又称 持久化缓存
合理利用这两种缓存策略,可以显著提升前端应用的性能和开发体验。
两种缓存的配合
一般来说,现代的打包工具都是同时开启这两种缓存。
在开发模式下,Webpack 会在系统空闲时,单独开启一个 Workers 线程把增量编译的结果从内存中写入到文件缓存中。
Webpack 一般会将文件缓存读取到内存中,在构建过程中根据文件内容确定文件是否发生变更,来确定重新编译还是使用缓存,这个就是 加速二次编译
二、配置
生产环境: 开启持久化缓存,缓存编译结果,输出文件生成 hash 值;
开发环境: 开启内存缓存,缓存编译结果,配置开发服务器devServer
,开启热重载;
1、开启缓存
开发环境可以配置内存缓存。生产环境开启持久化缓存。
Webpack 5 引入了持久化缓存功能,可以将模块的编译结果存储在磁盘上,以便在后续构建中重用。这可以显著减少构建时间。
module.exports = {
// 二者作用一致
cache: true,
cache: {
type: "memory", // 内存缓存
type: "filesystem", // 持久化缓存
},
};
2、配置开发服务器,并启动热重载
开发模式需要配置,生产环境不需要
// webpack.config.js
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000,
hot: true
}
3、生成文件配置哈希值
Webpack 可以根据文件内容生成一个唯一的哈希值,并将其添加到文件名中。这样,每当文件内容发生变化时,文件名也会随之改变,从而使浏览器加载新的文件,而旧的文件仍然可以从缓存中获取。生产和测试环境都需要配置
// webpack.config.js
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist')
}
4、缓存编译结果
我们可能使用 Eslint
去检查代码,使用 Babel
编译代码,vue
框架下 vue
文件的编译结果。每次重新编译的话,速度比较慢。
我们可以缓存之前的结果,这样第二次打包时速度就会更快了。
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: undefined, // 开发模式没有输出,不需要指定输出目录
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
// clean: true, // 开发模式没有输出,不需要清空输出结果
},
module: {
rules: [
{
test: /\.js$/,
// exclude: /node_modules/, // 排除node_modules代码不编译
include: path.resolve(__dirname, "../src"), // 也可以用包含
loader: "babel-loader",
options: {
cacheDirectory: true, // 开启babel编译缓存
cacheCompression: false, // 缓存文件不要压缩
},
},
{
test: /\.vue$/,
loader: "vue-loader", // 内部会给vue文件注入HMR功能代码
options: {
// 开启缓存
cacheDirectory: path.resolve(__dirname, "node_modules/.cache/vue-loader"),
},
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
exclude: "node_modules", // 默认值
cache: true, // 开启缓存
// 缓存目录
cacheLocation: path.resolve(
__dirname,
"../node_modules/.cache/.eslintcache"
),
}),
],
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000, // 模块体积≥30KB才切割
maxAsyncRequests: 6, // 并行加载的Chunk数上限
cacheGroups: {
// 第三方库组
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: 10, // 优先级最高
name(module) {
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/);
return `npm.${packageName.replace('@', '')}`; // 按包名独立切割(如 npm.lodash)
}
},
// 公共业务代码组
commons: {
minChunks: 3, // 被3+入口引用的模块
reuseExistingChunk: true,
filename: 'commons.[contenthash].js'
}
}
}
}
mode: "development",
devtool: "cheap-module-source-map",
// 开发服务器
devServer: {
host: "localhost", // 启动服务器域名
port: "3000", // 启动服务器端口号
open: true, // 是否自动打开浏览器
hot: true, // 开启HMR功能
},
};
更新日志
2025/8/24 08:17
查看所有更新日志
e7112
-1于