Skip to content

第七步:排查时最实用的顺序 ​

本节目标:理解“第七步:排查时最实用的顺序”的核心思路,并能把它用于实际开发或面试表达。 1)先看是不是被别的机制接管 先排除是不是 bfcache 恢复、Service Worker 命中。否则你盯 HTTP 头会越看越乱。(MDN Web Docs) 2)再看这次请求有没有主动改缓存模式 看是否是刷新、强刷、DevTools 关闭缓存,或者代码里用了 fetch(..., { cache })。普通 reload 和 force reload 往往会在请求头上体现为 max-age=0 / no-cache。(MDN Web Docs) 3)再看响应头三件套 先看 Cache-Control / Expires 决定新鲜度,再看 ETag / Last-Modified 决定验证方式,再看 Vary 决定缓存 key。绝大多数问题都在这三组里。(MDN Web Docs) 4)最后看是不是启发式缓存 如果你什么缓存头都没配,浏览器仍可能缓存一阵子。那通常就是启发式缓存在起作用。(RFC Editor) Last-Modified 一方面可以在以后作为条件请求的验证器使用,另一方面在没有 Cache-Control / Expires 时,也可能被缓存拿来做启发式缓存判断。RFC 9111 里明确说了,没有显式 freshness 信息时,缓存可以使用启发式过期策略;如果有 Last-Modified,常见做法会参考“距离上次修改时间的一小部分”,典型值常被举例为约 10%。

最简代码示例1)HTML 壳:每次都可存,但复用前先验证 HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Cache-Control: no-cache ETag: "page-shell-v12" Last-Modified: Sat, 21 Mar 2026 12:00:00 GMT Vary: Accept-Encoding 这套适合:

  • HTML 内容经常变;
  • 但你又不想完全禁用缓存;
  • 希望浏览器走 304 而不是每次都下完整正文。(MDN Web Docs)

2)带 hash 的静态资源:长缓存 + 不重验证 HTTP/1.1 200 OK Content-Type: application/javascript Cache-Control: public, max-age=31536000, immutable Vary: Accept-Encoding 这套适合:

  • /assets/app.8f3ab1.js
  • /assets/logo.4c77d9.png

也就是内容变了就换 URL 的资源。(MDN Web Docs)

3)个性化接口:浏览器不要存 HTTP/1.1 200 OK Content-Type: application/json Cache-Control: private, no-store 这套适合:

  • 当前登录用户资料
  • 余额、订单、权限信息
  • 任何你不希望浏览器留下可复用副本的响应。(MDN Web Docs)

4)前端代码主动改缓存行为 // 完全绕过 HTTP cache,也不把结果写回缓存 await fetch('/api/profile', { cache: 'no-store' }) // 即使本地有缓存,也先做条件验证 await fetch('/api/news', { cache: 'no-cache' }) // 有缓存就直接用,哪怕 stale await fetch('/dict.json', { cache: 'force-cache' }) 这些模式会直接影响浏览器这次请求和 HTTP cache 的交互方式。(MDN Web Docs)

本站总访问 — 次