聊天讨论 浏览器缓存最强攻略:强缓存、协商缓存、CDN、更新策略,一篇搞定

193577746(kyriewen) · 2026年06月05日 · 15 次阅读

网站加载慢?重复请求浪费带宽?用户总是看到旧版本?这些问题背后,都指向同一个关键词:缓存。今天我们从 HTTP 头开始,彻底搞懂强缓存、协商缓存、CDN 缓存、前端静态资源版本管理,以及最常见的缓存坑和解决方案。

一、缓存是什么?为什么重要?

缓存是 HTTP 协议中用于复用之前获取的资源的机制。合理使用缓存可以:

  • 减少网络请求,页面加载更快
  • 降低服务器压力
  • 节省用户流量

但缓存用不好,会导致用户看到过期内容,或者每次都重新下载,失去缓存意义。

二、强缓存:服务器告诉浏览器 “别问了,直接用旧的”

强缓存由服务器返回的响应头中的 Cache-Control(HTTP/1.1)或 Expires(HTTP/1.0,已过时)控制。

2.1 Cache-Control 常用指令

指令 含义
max-age=3600 资源在 3600 秒内是 “新鲜的”,直接使用缓存,不请求服务器
no-cache 跳过强缓存,但可以用协商缓存(见下文)
no-store 完全不缓存,每次都重新下载
public 可以被任何中间节点(CDN、代理)缓存
private 只能被浏览器缓存,不能给中间节点(如用户个人信息)
immutable 资源永不变化(通常配合带 hash 的文件名使用),浏览器不必再验证

2.2 强缓存流程

浏览器请求资源 → 服务器返回资源 + Cache-Control: max-age=3600
→ 浏览器缓存该资源,3600秒内再次请求直接读缓存(200 from disk cache)
→ 3600秒后重新请求服务器

2.3 如何绕过强缓存?

  • 刷新页面(F5 / Cmd+R):浏览器会带上 Cache-Control: max-age=0,告诉服务器不要用缓存,走协商缓存。
  • 硬刷新(Ctrl+F5 / Cmd+Shift+R):浏览器带上 Cache-Control: no-cache,强制重新下载。

三、协商缓存:浏览器问服务器 “资源变了吗?”

当强缓存过期,或者请求头带有 Cache-Control: no-cache 时,浏览器会发起协商缓存请求,询问服务器资源是否有更新。

3.1 Last-Modified / If-Modified-Since

服务器返回 Last-Modified(资源最后修改时间),浏览器下次请求带上 If-Modified-Since。服务器比对时间,若未修改则返回 304 Not Modified,浏览器使用缓存;若修改则返回 200 和新资源。

缺点

  • 时间精度为秒,如果文件在 1 秒内多次修改,可能无法检测到。
  • 如果文件内容没变但时间变了(如 CI 重新生成),也会导致重新下载。

3.2 ETag / If-None-Match(推荐)

ETag 是服务器根据文件内容生成的唯一标识(哈希值),更精确。浏览器下次请求带上 If-None-Match: "某hash"。若未变则返回 304,否则返回 200 和新资源。

优先级:ETag 高于 Last-Modified。

3.3 协商缓存流程

浏览器: 我有个资源,ETag是"abc",你变了没?
服务器: 没变,304,你继续用旧的
浏览器: (用缓存)

四、强缓存 vs 协商缓存对比

特性 强缓存 协商缓存
发起请求 不发(直接用缓存) 发,但服务端不返回体
状态码 200 (from disk/memory cache) 304
控制头 Cache-Control / Expires Last-Modified / ETag
适用场景 不常变的静态资源(JS/CSS/图片) 可能变化的 HTML、API 响应

五、最佳实践:如何配置?

5.1 静态资源(JS/CSS/图片):强缓存 + 文件名 hash

location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

注意:文件名必须带 hash(如 main.a3f2b1c.js),内容变化时 hash 变化,浏览器才会重新下载。这是目前最主流的前端静态资源缓存策略。

5.2 HTML 文件:协商缓存或 no-cache

location ~ \.html$ {
    add_header Cache-Control "no-cache";
}

因为 HTML 需要随时更新(入口文件),不能强缓存。

5.3 API 响应:按需

  • 动态数据:Cache-Control: no-cache
  • 相对固定的数据(如配置):Cache-Control: max-age=60(短时缓存)

六、前端更新痛点与解决方案

问题:用户看到旧版本

常见于:

  • 部署新版本后,用户浏览器缓存的旧 CSS/JS 未更新,导致页面错乱。
  • 入口 HTML 被强缓存,用户没拿到新版本入口,自然不会请求新资源。

解决方案:

  1. HTML 文件用协商缓存或短时缓存(如 max-age=60)。
  2. 静态资源用文件名 hash + 强缓存
  3. 通过构建工具(Webpack/Vite)自动生成带 hash 的文件名
  4. 部署时先上静态资源,后上 HTML。确保 HTML 引用的是最新的资源 hash。
  5. 可选项:在 HTML 中插入版本号或 query string(不推荐,因为可能被代理忽略)。

七、CDN 缓存

CDN 是 “反向代理缓存”,缓存静态资源在全球边缘节点。配置时需注意:

  • 通过 Cache-Control: public 允许 CDN 缓存。
  • 设置合适的 max-age,太短会增加回源请求,太长会导致更新不及时。
  • 刷新 CDN 缓存通常需要手动调用 API 或版本化 URL。

八、调试缓存

Chrome DevTools:

  • Network 面板:Size 列显示 (memory cache)(disk cache) 或状态码 304。
  • Disable cache 复选框:临时禁止缓存(仅限 DevTools 开启时)。
  • ApplicationCache Storage:查看 Service Worker 缓存。
  • Clear site data:清除当前网站的缓存。

常用命令:

  • 硬刷新:Cmd+Shift+R (Mac) / Ctrl+F5 (Windows)
  • 清除缓存并硬刷新:打开 DevTools 后右键刷新按钮选择 “Empty Cache and Hard Reload”

九、常见坑点

原因 解决
上线后用户还是旧版本 HTML 被强缓存 HTML 用 no-cache 或短时缓存
CSS 改了,页面样式还是旧的 CSS 文件名没变,浏览器强缓存 文件名加 hash
图片更新了,还是旧图 CDN 缓存未刷新 版本化 URL 或主动刷新 CDN
304 请求多,还是慢 强缓存没开,每次都协商 给静态资源加 max-age

十、总结

场景 推荐配置
静态资源(带 hash) Cache-Control: max-age=31536000, immutable
HTML 入口 Cache-Control: no-cache
API(不变数据) Cache-Control: max-age=60
API(动态) Cache-Control: no-cache
用户头像等私有资源 Cache-Control: private, max-age=3600

缓存策略没有 “标准答案”,需要根据业务需求权衡实时性和性能。但记住:带 hash 的静态资源放心强缓存,入口文件绝不强缓存

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请 注册新账号