首页 / 互联网开发 / 正文

HTTP 缓存一篇讲透:强缓存、协商缓存与资源指纹

做 Web 性能优化,缓存是性价比最高的一步——不用换服务器、不用改业务代码,把响应头配对,重复请求就能少一大半。但缓存也是最容易配错的一环:“更新了用户看不到新版本”“改了配置还是没生效”,多半是强缓存与协商缓存没分清。这篇把它们彻底讲透。

一、两种缓存:强缓存与协商缓存

类型判定依据命中表现谁决定
强缓存Cache-Control(或 Expires)200(from memory/disk cache),不发网络请求浏览器本地直接用
协商缓存ETag / Last-Modified304 Not Modified,仍需发请求确认服务器返回 304 或 200
记忆锚点:强缓存 = 不发请求直接用;协商缓存 = 发一个“校验请求”问服务器“我没变吧”,服务器说“没变”(304)就继续用本地副本。

二、强缓存的头:Cache-Control 是主角

# 常见取值
Cache-Control: public, max-age=31536000   # 一年,适合带指纹的静态资源
Cache-Control: private, max-age=0         # 仅本用户、不缓存,适合登录后页面
Cache-Control: no-cache                   # 每次都要到服务器“协商”,不是不缓存
Cache-Control: no-store                   # 真正不缓存(敏感数据)
Cache-Control: public, max-age=60, stale-while-revalidate=600
  • max-age 单位是秒,表示从收到响应起多久内可用;
  • 老字段 Expires(HTTP/1.0)是绝对时间,受本地时钟影响,现在以 Cache-Control 为准,两者都有时 Cache-Control 优先;
  • no-cache 不是“不用缓存”,而是“每次先用再用,但要先校验”——这正适合 HTML 页面。

三、协商缓存的头:ETag 与 Last-Modified

  • Last-Modified / If-Modified-Since:基于文件的最后修改时间,精度到秒,时间没变服务器返回 304;
  • ETag / If-None-Match:基于内容的校验值(指纹),内容变指纹才变,比时间更准,是 HTTP/1.1 的推荐方式;
  • 两者都带时,服务器以 ETag 校验优先(If-None-Match 优先于 If-Modified-Since)。
# 服务器返回
HTTP/1.1 200 OK
Cache-Control: no-cache
ETag: "64c1a2-5d4e"
# 浏览器再请求时带上
If-None-Match: "64c1a2-5d4e"
# 内容没变 → 服务器返回
HTTP/1.1 304 Not Modified   # 不带响应体,省流量省时间

四、工程实践:HTML 与静态资源要区别对待

最经典的策略是“内容指纹 + 长缓存”

  1. 构建工具(webpack/Vite)给 JS/CSS 文件名加上内容哈希,如 app.a1b2c3.js——内容变了文件名就变;
  2. 带哈希的静态资源配长缓存(一年):文件永远不变,放心缓存;
  3. HTML(index.html)配 no-cache:每次都协商校验,一旦返回新页面,就引用了带新哈希的资源,天然实现“更新即生效”;
  4. 图片、字体等不变资源同样长缓存;需要换图时直接换文件名或加参数。
最常见的线上事故就是这样来的:HTML 被长缓存了,用户永远拿不到新页面;或资源没有指纹还长缓存,发布后老用户白屏、样式错乱。排查时先在浏览器控制台勾选 Disable cache 或强制刷新确认是不是缓存问题。

五、Nginx 里的落地配置

# 带指纹的静态资源:一年强缓存
location /assets/ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}
# HTML:不缓存,每次协商
location = /index.html {
    add_header Cache-Control "no-cache";
}
# 普通页面:短缓存,配合后端协商
location / {
    add_header Cache-Control "no-cache";
}
immutable 表示“文件绝不会变”,配合指纹资源使用,浏览器可以跳过每次的重新验证,是官方推荐的写法。

六、调试缓存:DevTools 里看四个信息

  • Size 列:from memory cache / from disk cache 说明强缓存命中;
  • Status304 说明走了协商缓存;
  • Response Headers 里的 Cache-Control、ETag、Last-Modified 值;
  • 勾选 Disable cache 后的加载时间对比——能直观看到缓存省了多少。

缓存配对了,静态资源这部分的性能基本就位了。缓存之外,还有压缩、CDN、图片格式等更多优化手段,见前端首屏性能优化清单