Cache-Control:no-cache 与 no-store 区别
no-store 和 no-cache 是 HTTP 缓存头(Cache-Control)中最容易混淆的两个指令。它们的核心区别在于:no-cache 允许缓存,但使用前必须验证;no-store 彻底禁止缓存,连存都不准存。
为了方便记忆,你可以这样理解:
no-cache = 有缓存,但不信任,每次都问一下服务器。
no-store = 坚决不存任何副本,用完即焚。
以下是详细对比:
1. 核心机制对比
| 特性 | no-cache | no-store |
|---|---|---|
| 是否允许存储 | 允许。浏览器和代理服务器可以将响应存入硬盘或内存。 | 禁止。不得以任何形式(内存、硬盘)保存响应副本。 |
| 使用缓存前 | 必须重新验证。每次使用缓存时,都必须向源服务器发起条件请求(携带 If-Modified-Since 或 ETag)。 | 不涉及验证。因为根本没存,每次都直接请求源服务器获取完整数据。 |
| 服务器返回 304 时 | 若服务器返回 304 Not Modified,则可继续使用已存储的旧缓存。 | 永远不会发生 304,因为客户端没有缓存可用,服务器必须返回 200 完整数据。 |
| 网络开销 | 每次都有验证请求(请求头小,响应体无或小)。 | 每次都有完整请求(请求头 + 完整的响应体)。 |
2. 实际浏览器行为差异(关键)
no-cache场景:你访问页面,浏览器发现有缓存,但标了no-cache。浏览器会连接服务器问一句:“这个资源有没有变?”(发 ETag)。服务器说:“没变”(304),浏览器就直接展示本地缓存,省下了下载图片/JS/CSS 的带宽和时间。no-store场景:你访问页面,浏览器发现有缓存,但标了no-store。浏览器直接忽略该缓存(甚至不会写入磁盘),立刻向服务器请求完整的新数据。就算服务器没变,也必须把完整的 HTML/数据重新下载一遍。
3. 涉及敏感信息时的安全语义(RFC 规范)
在 HTTP 规范(RFC 9111)中,no-store 不仅仅是“不缓存”,它还包含隐私安全的考量:
- 即使请求/响应需要存到非持久性存储(比如浏览器的内存缓存)以便前进/后退时快速展示,理论上也不应该存储(必须尽量清除)。
- 而
no-cache没有这个安全约束,它只关乎“新鲜度”,不关乎“保密性”。
4. 常见误用纠正
很多开发者误以为 no-cache 就是“不缓存”,这是绝对错误的。如果你希望页面完全不缓存,每次都拿最新的,正确的写法是 no-store,而不是 no-cache。
- ❌ 错误:
Cache-Control: no-cache(浏览器依然会存,只是每次去问一下,如果服务器宕机或网络差,甚至可能直接报错无法访问,因为验证失败)。 - ✅ 正确:
Cache-Control: no-store, must-revalidate(用于交易页、支付页、验证码、实时股价)。
5. 最佳实践组合
在实际生产环境中,它们通常配合 must-revalidate 使用:
- 用于 HTML 页面(动态内容):
Cache-Control: no-cache, must-revalidate(每次都检查 HTML 是否有更新)。 - 用于敏感隐私数据(订单/支付):
Cache-Control: no-store, no-cache, must-revalidate(彻底不存,同时保证即使有历史缓存也要验证)。 - 用于静态资源(带 hash 的 JS/CSS/图片):
Cache-Control: public, max-age=31536000, immutable(一年内强缓存,根本不用no-cache)。