隐形层:精通 HTTP 缓存(第 2 部)

发布: (2026年2月17日 GMT+8 06:45)
5 分钟阅读
原文: Dev.to

Source: Dev.to

如果你曾经大喊:“我已经在数据库里更新了数据,但用户仍然看到旧的版本!”并且疯狂地强制刷新浏览器,你就遇到了 HTTP 缓存。

当你调用 fetch('/api/user') 时,浏览器不会立刻去网络请求,而是会执行一套严格的检查清单:

  1. Memory/Disk Check – 我本地是否已有该资源的副本?
  2. Expiration Check – 如果有,本地副本是否仍然新鲜(基于 max-age)?
  3. Short Circuit – 如果仍然新鲜,浏览器会立即返回数据,根本不与服务器通信。

这些步骤由 Cache‑Control 响应头控制。

Cache‑Control

最重要的网页性能响应头。它告诉浏览器该如何行为。

max-age(计时器)

Cache-Control: max-age=3600

数据在 1 小时(3600 秒)内保持新鲜。浏览器在此时间到期前不会再次向服务器请求。

陷阱: 如果你在 5 分钟 后部署了关键的 bug 修复,使用缓存版本的用户将在接下来的 55 分钟 内看不到该修复。

no-cacheno-store(常见混淆)

指令含义常见使用场景
no-store永不保存此响应。敏感数据(例如银行信息)或每毫秒都会变化的数据。
no-cache保存响应,但在使用前需向服务器重新验证。每次请求都需要最新版本的情况。

注意: no-cache 会强制浏览器在每次请求时询问服务器:“这个版本仍然有效吗?”

参考资料: MDN Web Docs – Cache‑Control

ETags 和 Last‑Modified(304 Not Modified)

在处理大型资源(例如,2 MB、包含 5,000 个商品的列表)时,你不想每次都下载整个文件。

  1. 首次请求: 服务器发送数据 以及 一个 ETag(唯一的哈希/指纹)。
  2. 后续请求: 浏览器在 If-None-Match 中把 ETag 发送回去。
  3. 服务器响应: 如果哈希匹配,服务器返回 304 Not Modified

结果: 浏览器复用缓存的版本,节省带宽和时间。

Stale‑While‑Revalidate(过期‑重新验证)

Cache-Control: max-age=60, stale-while-revalidate=600
  • 新鲜(≤ 60 秒): 直接从缓存即时返回。
  • 过期(60 秒 – 600 秒): 立即返回已过期的响应,同时在后台获取最新副本并更新缓存。

这样可以消除加载指示器,同时保持数据相对新鲜。

深入了解: web.dev – 爱你的缓存(stale‑while‑revalidate)

为什么这对 React 开发者很重要

你可能会想,“我只是前端开发者,根本不配置服务器头!”
现实是,你 无法用 JavaScript 修复因 HTTP 造成的问题

  • 如果 API 返回 Cache-Control: no-store,像 React Query(TanStack Query)这样的库就无法维护有效的客户端缓存,因为浏览器拒绝存储响应。
  • 如果 API 为用户资料返回 max-age=31536000(1 年),用户在缓存过期之前永远看不到资料的更新。

操作: 在 Chrome DevTools → Network(网络)标签页检查响应头。浏览器的“收据”系统(条件请求)会在资源未改变时返回 304,从而避免不必要的下载。

用户体验收益

  • Stale‑while‑revalidate 能在后台获取新数据的同时立即显示旧数据,省去加载动画的需求。
  • 正确的缓存头可以降低延迟、减少带宽消耗,并提升感知性能。

深入资源

  • MDN HTTP Caching Guide – 关于浏览器如何处理存储的综合手册。
  • Google Web.dev Guide – 关于配置头部以提升性能和 Lighthouse 分数的实用指南。
  • Cloudflare CDN Learning Center – 了解边缘缓存如何与浏览器缓存交互。

接下来是什么?

现在我们已经了解了不可见层,可以转向 Application Layer。在 Part 3 中,我们将探讨 React Query (TanStack Query) 并了解如何使用它实现高效的缓存系统。

在 Part 3 见。

0 浏览
Back to Blog

相关文章

阅读更多 »