HTTP 缓存是前端性能优化的核心手段,能大幅减少重复请求、降低服务器压力、提升页面加载速度。其中强缓存和协商缓存是最基础、最常用的两种缓存策略,本文从原理、区别、使用、优化四个维度彻底讲透。
一、前言:HTTP 缓存整体流程
浏览器请求资源时,会按先强缓存 → 后协商缓存的顺序判断:
1. 先检查强缓存:生效 → 直接使用本地缓存,不发请求
2. 强缓存失效 → 发起协商缓存请求:服务器校验通过 → 使用缓存(304),否则返回新资源(200)
二、强缓存:无需请求服务器,直接读本地
1. 核心定义
强缓存是最激进的缓存策略:浏览器判断本地缓存未过期时,完全不向服务器发送请求,直接从内存(Memory Cache)或磁盘(Disk Cache)读取资源。
2. 关键响应头
强缓存有两个控制头,HTTP1.1 的 Cache-Control 优先级高于 HTTP1.0 的 Expires。
(1)Expires(HTTP1.0,已不推荐)
- 格式:响应头返回绝对时间
- 原理:浏览器对比本地时间与该时间,未到则使用缓存
- 缺陷:依赖客户端本地时间,时间被修改会导致缓存失效/错乱
Expires: Wed, 03 Mar 2026 12:00:00 GMT
(2)Cache-Control(HTTP1.1,主流方案)
- 格式:返回相对时间(秒),不受本地时间影响
- 常用取值:
值 含义 max-age=xxx 缓存有效期,如 max-age=31536000(1年)public 所有节点(浏览器+CDN)均可缓存 private 仅浏览器可缓存(默认值) no-cache 不直接使用强缓存,强制走协商缓存 no-store 完全不缓存,每次都请求新资源 s-maxage=xxx 仅CDN等代理服务器生效,优先级高于max-age
Cache-Control: max-age=31536000, public
3. 表现特征
- Network 面板:
Size列显示(from memory cache)/(from disk cache) - 状态码:无请求,无状态码
- 优势:速度最快,零请求开销
三、协商缓存:发请求校验,服务器决定是否用缓存
1. 核心定义
强缓存失效后,浏览器会携带缓存标识向服务器发请求,服务器校验资源是否更新:
– 未更新 → 返回 304 Not Modified,浏览器用本地缓存
– 已更新 → 返回 200 OK + 新资源
2. 两组缓存标识(二选一,ETag 优先级更高)
(1)Last-Modified + If-Modified-Since(时间戳)
- 响应头:
Last-Modified服务器返回资源最后修改时间 - 请求头:
If-Modified-Since浏览器携带上次的修改时间 - 原理:服务器对比时间,未变则返回304
- 缺陷:
- 仅精确到秒,秒内多次修改无法识别
- 文件内容不变但修改时间改变,会误判为新资源
// 响应
Last-Modified: Tue, 02 Mar 2026 10:00:00 GMT
// 请求
If-Modified-Since: Tue, 02 Mar 2026 10:00:00 GMT
(2)ETag + If-None-Match(文件指纹,推荐)
- 响应头:
ETag服务器根据文件内容生成唯一哈希值(指纹) - 请求头:
If-None-Match浏览器携带上次的ETag - 原理:服务器对比指纹,完全一致则返回304
- 优势:精准识别文件内容变化,不受时间影响
// 响应
ETag: "5f3d2a1b-1234"
// 请求
If-None-Match: "5f3d2a1b-1234"
3. 表现特征
- Network 面板:有请求,状态码为 304 Not Modified
- 优势:比强缓存灵活,比无缓存省流量(仅返回响应头,无响应体)
四、强缓存 vs 协商缓存:核心区别与联系
1. 核心区别(表格版,适合博客展示)
| 维度 | 强缓存 | 协商缓存 |
|---|---|---|
| 是否发请求 | 不发请求 | 发请求(仅头部,无资源体) |
| 状态码 | 无请求,无状态码 | 304(命中)/200(未命中) |
| 控制头 | Expires、Cache-Control | Last-Modified/ETag |
| 优先级 | 高于协商缓存 | 强缓存失效后才触发 |
| 性能 | 最优 | 次之 |
| 灵活性 | 差(到期前无法更新) | 高(服务器实时校验) |
2. 二者联系
- 同属 HTTP 缓存:目标都是减少资源传输,提升加载速度
- 执行顺序固定:先校验强缓存,失效后再走协商缓存
- 互补使用:静态资源用强缓存,动态页面用协商缓存
五、实战使用:Nginx 配置 + 前端最佳实践
1. Nginx 缓存配置示例
区分静态资源(强缓存)和HTML(协商缓存),是前端最常用方案:
server {
# 1. JS/CSS/图片/字体:强缓存1年 + ETag协商兜底
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
expires 1y; # 强缓存1年
etag on; # 开启ETag
add_header Cache-Control "public, max-age=31536000";
}
# 2. HTML:禁用强缓存,强制协商缓存
location ~* \.html$ {
add_header Cache-Control "no-cache";
etag on;
expires -1; # 禁止强缓存
}
}
2. 前端工程化配合
- 静态资源(JS/CSS/图片):webpack/vite 打包加 hash 后缀(如
app.abc123.js) - 原理:文件内容变化 → hash 变化 → 视为新资源,强缓存自动失效
- 优势:既享受长时强缓存,又能实时更新
六、缓存优化与避坑注意点
1. 资源分类策略(核心)
- 静态资源(不变/少变):长时强缓存 + hash 命名
- HTML(入口文件):协商缓存(no-cache)
- 接口数据:按需缓存,敏感数据用
no-store
2. 头优先级必记
Cache-Control>ExpiresETag>Last-Modified- 同时配置时,只生效优先级高的
3. 易混淆概念澄清
no-cache≠ 不缓存:是跳过强缓存,直接走协商缓存no-store= 真不缓存:本地和服务器都不存储- 不要给所有资源加
no-cache,会浪费协商缓存请求
4. 性能与精准平衡
- 大文件:关闭 ETag(哈希计算耗性能),用 Last-Modified 即可
- CDN 场景:加
s-maxage控制代理缓存,避免CDN缓存过时资源 - 移动端:优先内存缓存,
max-age不宜过短(减少请求)
5. 调试技巧
- Chrome DevTools → Network:
Size列:memory/disk cache= 强缓存命中Status列:304= 协商缓存命中
- 禁用缓存:勾选
Disable Cache,调试时用
七、总结
- 强缓存:不发请求,靠
Cache-Control控制,速度最快,适合带hash的静态资源 - 协商缓存:发请求校验,靠
ETag/Last-Modified控制,灵活精准,适合HTML - 执行顺序:强缓存优先 → 失效走协商缓存
- 最佳实践:静态资源长强缓存+hash,HTML协商缓存,兼顾性能与更新
HTTP 缓存是前端必知必会的基础知识点,合理配置能让页面加载速度提升50%以上,是面试和工程优化的高频考点。






最新评论
这小生活不错呀
不错,必须顶一下!
看着你还在坚持,很好
看来忙了也没时间更新博客了
NIce。学习了。。。。
网站不错!!!!
简洁实用,好文章!
不错,过来支持一下