HTTP缓存是前端性能优化的核心手段。当您首次访问网站时,浏览器向服务器请求资源,服务器不仅会返回所需的CSS、JavaScript或图片文件,更会在响应头中设置的缓存指令,有些资源允许直接存档复用(强缓存),有些则需要定期"持证核验"(协商缓存)。浏览器再次请求时就会进行缓存验证。
一、HTTP缓存设置流程
HTTP缓存设置是通过响应头控制浏览器的,具体步骤如下:
浏览器发起资源请求
当浏览器首次请求静态资源(如GET /static/image.jpg),向服务器发送HTTP请求。
后端处理并生成缓存响应头
服务器收到请求后,生成响应并配置缓存策略头,如Cache-Control。常见策略包括:
max-age=3600:资源可缓存1小时,期间浏览器不重复请求。
no-cache:每次需验证资源是否过期(协商缓存)。
no-store:禁止缓存,每次请求都从服务器获取最新内容。
可能配合其他头部(如Expires、ETag)增强控制。
返回资源及缓存头信息
服务器将资源数据与缓存头一并返回浏览器(状态码200 OK)。
浏览器解析并缓存资源
浏览器根据响应头策略存储资源到本地缓存:
若为强缓存(如max-age未过期),后续请求直接读取缓存,无需网络请求。
若为协商缓存(如no-cache或max-age过期),后续请求会携带If-None-Match(基于ETag)或If-Modified-Since(基于Last-Modified)向服务器验证,若未修改则返回304,浏览器使用缓存;若已修改则返回新资源。
二、缓存机制
强缓存
原理:直接复用本地缓存,不向服务器发送请求。
响应头:
Cache-Control: max-age=3600(优先级高于 Expires)。
Cache-Control: immutable(有效期内禁止所有验证,包括普通刷新)。
Expires(HTTP/1.0,指定过期时间)。
适用场景:
通用静态资源(图片、CSS、JS)→ max-age + Expires。
哈希命名的资源(如 app.a1b2c3.js)→ 必加 immutable。
协商缓存
原理:强缓存失效后,向服务器验证资源是否更新。
头字段:
Last-Modified(资源最后修改时间) + If-Modified-Since。
ETag(资源唯一标识) + If-None-Match(优先级更高)。
结果:服务器返回 304 Not Modified(复用缓存)或 200 OK(新资源)。
Cache-Control 常用指令
属性作用行为适用场景注意事项
no-cache
跳过强缓存,直接进入协商缓存
浏览器每次请求资源时,必须向服务器验证资源是否更新(发送 If-None-Match 等头)。
需要频繁更新的资源(如入口 HTML 文件),避免强缓存导致用户无法及时获取新内容。
不禁止缓存,只是强制协商验证。需配合 ETag 或 Last-Modified 使用。
no-store
完全禁止缓存
浏览器和代理服务器都不缓存资源,每次请求都直接从服务器下载完整内容。
敏感数据(如用户隐私信息、实时 API 响应),确保数据不被存储。
会显著增加服务器负载,仅限必要场景使用。
public
允许中间代理(如 CDN、反向代理)缓存资源
资源可被浏览器和代理服务器缓存。
公共静态资源(如图片、CSS、JS 文件),通过代理缓存提升全球用户的访问速度。
默认情况下,带有 Authorization 头的请求会被视为 private,需显式设置 public。
private
仅允许浏览器缓存,禁止代理服务器缓存
资源仅缓存在用户本地,代理服务器不存储。
用户个性化数据(如登录后的页面内容),避免代理缓存泄露隐私。
即使设置了 private,浏览器仍可能因内存不足提前清除缓存。
三、不同刷新操作的缓存行为
操作类型强缓存是否生效协商缓存是否生效HTTP 请求是否发送最终结果
地址栏输入/页面跳转
✔️ 是(若未过期)
❌ 否(强缓存生效时)
否(强缓存有效时)
200 (from disk/memory cache)
❌ 否(若过期)
✔️ 是(触发验证)
是(强缓存过期时)
304 Not Modified 或 200 OK
普通刷新(F5)
❌ 否
✔️ 是
是
304 Not Modified 或 200 OK
强制刷新(Ctrl + F5)
❌ 否
❌ 否
是(强制请求最新资源)
200 OK(直接下载新资源)
表格说明
地址栏输入/页面跳转:
强缓存优先:若资源未过期(max-age 有效),直接使用缓存,不发送请求。
协商缓存后备:若强缓存过期,发送请求并验证协商缓存。
普通刷新(F5):
强制触发协商缓存:即使强缓存未过期,浏览器也会发送请求验证资源新鲜度。
强制刷新(Ctrl + F5):
完全绕过所有缓存:强制从服务器下载最新资源,覆盖本地缓存。
四、最佳实践
静态资源优化
文件名哈希(如 app.a1b2c3.js)实现永久缓存。
配置 max-age=1y + immutable,避免重复验证。
入口文件(HTML)
使用 no-cache 或短缓存,确保及时更新。
服务器配置(Nginx示例):
location /static/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
五、调试工具验证
Chrome DevTools → Network 面板:
观察请求的 Size 列:
(from memory cache) 或 (from disk cache) → 强缓存生效。
304 Not Modified → 协商缓存生效。
200(无缓存标记)→ 新资源下载。
Waterfall 列:查看是否发送验证请求。
命令行检测:
curl -I http://example.com/resource.js
检查响应头的 Cache-Control、ETag 等字段。
六、常见问题
缓存导致更新延迟?
解决:文件名哈希 + CDN 缓存刷新。
用户看到旧版本页面?
解决:Service Worker 主动更新策略,提示用户刷新。
敏感信息泄露?
避免:切勿缓存私有数据(如 API 响应),使用 no-store。