回答这个问题,有两个参与者,客户端(请求)和服务器(响应)。
客户端:
客户端只能使用一种缓存方法进行请求。有不同的方法,如果未指定,则会使用默认值。
- default: 检查浏览器缓存:
- 如果已经缓存并且“新鲜”:从缓存中返回。
- 如果已经缓存,但是“陈旧”,但仍然“有效”:从缓存中返回,并安排一个获取以更新缓存(供下一次使用)。
- 如果已经缓存并且“陈旧”:带条件获取、缓存和返回。
- 如果没有缓存:获取、缓存并返回。
- no-store: 获取并返回。
- reload: 获取、缓存并返回。(默认-4)
- no-cache: 检查浏览器缓存:
- 如果已经缓存:带条件获取、缓存并返回。(默认-3)
- 如果没有缓存:获取、缓存并返回。(默认-4)
- force-cache: 检查浏览器缓存:
- 如果已经缓存:无论是否过期都返回它。
- 如果没有缓存:获取、缓存并返回。(默认-4)
- only-if-cached: 检查浏览器缓存:
- 如果已经缓存:无论是否过期都返回它。
- 如果没有缓存:抛出网络错误。
注释:
- 仍然“有效”意味着当前的
age
在stale-while-revalidate
的生命周期内。它需要“重新验证”,但仍可返回。
- 这里的“获取”(Fetch)为简单起见,是指“非条件网络获取”。
- “带条件获取”(Fetch with conditions)意味着使用诸如
If-Modified-Since
或ETag
等头来获取,以便服务器可以响应304:(未修改)
。
https://fetch.spec.whatwg.org/#concept-request-cache-mode
服务器:
现在我们了解了客户端的功能,服务器响应就更有意义了。查看Cache-Control头部,如果服务器返回:
- no-store:告诉客户端根本不要使用缓存
- no-cache:告诉客户端应该进行条件请求并忽略新鲜度
- max-age:告诉客户端缓存保持“新鲜”的时间
- stale-while-revalidate:告诉客户端缓存保持“有效”的时间
- immutable:永久缓存
现在我们可以把它们结合起来。这意味着唯一的可能性是:
- 非条件网络获取
- 有条件的网络获取
- 返回陈旧的缓存
- 返回陈旧但有效的缓存
- 返回新鲜的缓存
- 返回任何缓存
任何客户端或服务器的组合都可以决定使用哪种方法或一组方法。如果服务器返回
no-store
,无论客户端请求类型如何,它都不会命中缓存。如果客户端请求是
no-store
,不管服务器返回什么,它都不会缓存。如果客户端没有指定请求类型,则服务器将用
Cache-Control
来指定。
服务器同时返回
no-cache
和
no-store
是没有意义的,因为
no-store
会覆盖所有设置。是的,你可能经常看到这两个选项一起使用,但在浏览器实现正常的情况下,这是无用的。不过,
no-store
自1999年以来就已经成为规范的一部分了:
https://datatracker.ietf.org/doc/html/rfc2616#section-14.9.2
在实际使用中,如果你的服务器支持
304:未修改
,并且想使用客户端缓存来提高速度,但仍然希望强制进行网络获取,请使用
no-cache
。如果不支持
304
,并且想强制进行网络获取,请使用
no-store
。如果你可以接受有时候使用缓存,请使用新鲜度和重新验证头信息。
实际上,如果在客户端混淆了
no-cache
和
no-store
,那么几乎不会有什么变化。然后,只会发送几个头文件,并且浏览器将处理不同的内部响应。如果使用
no-cache
,然后忘记稍后使用它,可能会出现问题。
no-cache
告诉浏览器将响应存储在缓存中,而没有它的后续请求可能会触发内部缓存。
有时,您可能希望根据上下文甚至在同一资源上混合使用方法。例如,您可能希望在服务工作者和后台同步上使用
reload
,但在网页本身上使用
default
。这就是您可以按照自己的意愿操纵用户代理(浏览器)缓存的地方。只需记住,服务器通常最终决定缓存的工作方式。
为了澄清可能发生的混淆,
客户端 可以在
请求 中使用
Cache-Control
头部,告诉服务器在响应时不要使用自己的缓存系统。这与浏览器/服务器动态无关,更多地涉及服务器/数据库动态。
另外,
no-store
在技术上意味着不能存储到任何非易失性存储(磁盘)并尽快从易失性存储(内存)中释放。实际上,这意味着根本不使用缓存。这个命令实际上是双向的。带有
no-store
的客户端请求不应写入磁盘或数据库,并且是短暂的。
TL;DR:
no-store
会覆盖
no-cache
。同时设置这两个选项是无用的,除非我们在讨论超出规范或不支持
no-store
的 HTTP/1.0 浏览器(例如 IE11)。使用
no-cache
支持
304
。