浏览器缓存机制是什么?强缓存和协商缓存的区别?

缓存流程

请求 → 检查强缓存 → 命中?→ 直接使用(不发请求)
                   ↓ 未命中
         检查协商缓存 → 命中?→ 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),内容变化时文件名变,自动请求新文件。

同分类其他题目