浏览器缓存机制是什么?强缓存和协商缓存的区别?
缓存流程
请求 → 检查强缓存 → 命中?→ 直接使用(不发请求)
↓ 未命中
检查协商缓存 → 命中?→ 304 使用缓存
↓ 未命中
200 返回新资源强缓存
不发请求,直接从缓存读取。
HTTP/1.1:Cache-Control(优先)
Cache-Control: max-age=3600 # 缓存 3600 秒
Cache-Control: no-cache # 不直接使用缓存(走协商缓存)
Cache-Control: no-store # 完全不缓存
Cache-Control: public # 可被 CDN 等中间缓存
Cache-Control: private # 只能被浏览器缓存HTTP/1.0:Expires(已过时)
Expires: Wed, 09 Aug 2026 00:00:00 GMT # 绝对过期时间协商缓存
发请求验证缓存是否有效,有效返回 304。
方式 1:Last-Modified / If-Modified-Since
# 首次响应
Last-Modified: Wed, 09 Aug 2026 00:00:00 GMT
# 再次请求
If-Modified-Since: Wed, 09 Aug 2026 00:00:00 GMT
# 服务器比较:
# 未修改 → 304 Not Modified(不返回响应体)
# 已修改 → 200 + 新资源 + 新 Last-Modified方式 2:ETag / If-None-Match(更精确)
# 首次响应
ETag: "abc123"
# 再次请求
If-None-Match: "abc123"
# 服务器比较:
# ETag 相同 → 304
# ETag 不同 → 200 + 新资源ETag vs Last-Modified
| 特性 | Last-Modified | ETag |
|---|---|---|
| 精度 | 秒级 | 字节级(哈希) |
| 性能 | 快(时间比较) | 稍慢(计算哈希) |
| 准确性 | 低(1秒内修改无法检测) | 高 |
| 优先级 | 低 | 高 |
实际应用
HTML 文件:Cache-Control: no-cache(协商缓存)
JS/CSS 文件:Cache-Control: max-age=31536000 + 文件名哈希(强缓存)
图片等静态资源:Cache-Control: max-age=86400(强缓存)
# Nginx 配置示例
location ~* \.(js|css)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
location ~* \.(html)$ {
add_header Cache-Control "no-cache";
}immutable 关键字
immutable 告诉浏览器资源永不过期,即使用户刷新也不验证:
Cache-Control: max-age=31536000, immutable配合文件名哈希(如 app.a1b2c3.js),内容变化时文件名变,自动请求新文件。