为了回答这个问题,这里有两个参与者,客户端(请求)和服务器(响应)。
客户:
客户端只能使用一种缓存方法进行请求。有不同的方法,如果没有指定,将使用default
.
- 默认:检查浏览器缓存:
- 如果缓存并且“新鲜”:从缓存中返回。
- 如果缓存,陈旧,但仍然“有效”:从缓存返回,并安排一次获取以更新缓存(供下次使用)。
- 如果缓存和陈旧:获取条件、缓存并返回。
- 如果未缓存:获取、缓存并返回。
- no-store:获取并返回。
- reload:获取、缓存和返回。(默认-4)
- no-cache:检查浏览器缓存:
- 如果缓存:带条件获取、缓存并返回。(默认-3)
- 如果未缓存:获取、缓存并返回。(默认-4)
- force-cache:检查浏览器缓存:
- 如果缓存:无论是否过时都返回它。
- 如果不缓存:获取、缓存并返回。(默认-4)
- only-if-cached:检查浏览器缓存:
- 如果缓存:无论是否过时都返回它。
- 如果没有缓存:抛出网络错误。
笔记:
- 仍然“有效”意味着电流
age
在stale-while-revalidate
生命周期内。它需要“重新验证”,但仍然可以退货。
- 这里的“Fetch”,为简单起见,是“non-conditional network fetch”的缩写。
- “带条件获取”意味着使用诸如 的标头进行获取
If-Modified-Since
,或者ETag
服务器可以使用304: (Not Modified)
.
https://fetch.spec.whatwg.org/#concept-request-cache-mode
服务器: :
现在我们了解了客户端可以做什么,服务器响应就更有意义了。查看Cache-Control
标头,如果服务器返回:
- no-store:告诉客户端根本不使用缓存
- no-cache:告诉客户端它应该执行条件请求并忽略新鲜度
- max-age:告诉客户端缓存“新鲜”多长时间
- stale-while-revalidate:告诉客户端缓存“有效”多长时间
- 不可变:永远缓存
现在我们可以把它们放在一起。这意味着唯一的可能性是:
- 非条件网络获取
- 条件网络获取
- 返回过时的缓存
- 返回陈旧但有效的缓存
- 返回新的缓存
- 返回任何缓存
客户端或服务器的任何组合都可以指定要使用的方法或方法集。如果服务器返回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: Not Modified
,并且您想使用客户端缓存作为提高速度的一种方式,但仍想强制网络获取,请使用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
. 两者都设置是没有用的,除非我们谈论的是不支持的或不支持的 HTTP/1.0 浏览器no-store
(也许是 IE11?)。用于no-cache
支持304
。