另一个工具,可帮助您在提供 Web 应用时平衡即时性和新鲜度。
哪些商品已发货?
stale-while-revalidate
可帮助开发者在即时性(立即加载缓存的内容)与新鲜度(确保将来使用对缓存内容的更新)之间取得平衡。如果您维护的第三方网络服务或库定期更新,或者第一方资产的生命周期往往较短,那么 stale-while-revalidate
可能是对现有缓存政策的补充。
Chrome 75 和 Firefox 68 支持在 Cache-Control
响应标头中设置 stale-while-revalidate
和 max-age
。
不支持 stale-while-revalidate
的浏览器会以静默方式忽略该配置值,并使用 max-age
,我稍后会加以说明...
这是什么意思?
我们将 stale-while-revalidate
分为两部分:缓存响应可能已过时的概念以及重新验证过程。
首先,浏览器如何知道缓存的响应是否为“过时”?包含 stale-while-revalidate
的 Cache-Control
响应标头也应包含 max-age
,通过 max-age
指定的秒数是确定过时的决定因素。任何更新于 max-age
的缓存响应都被视为最新响应,而较旧的缓存响应则已过时。
如果本地缓存的响应仍处于最新状态,则可以按原样使用该响应来满足浏览器的请求。从 stale-while-revalidate
的角度来看,在这种情况下,无需执行任何操作。
但是,如果缓存响应已过时,系统会执行另一项基于存在时间的检查:缓存响应的存在时间是否位于 stale-while-revalidate
设置提供的额外时间段内?
如果过时响应的存在时间在此窗口中,则将用于满足浏览器的请求。同时,对网络发出“重新验证”请求不会延迟使用已缓存响应。返回的响应可能包含与先前缓存的响应相同的信息,也可能不同。无论采用哪种方式,网络响应都会存储在本地,替换之前缓存的内容,并重置将来的任何 max-age
比较中使用的“新鲜度”计时器。
但是,如果过时的缓存响应已经足够老,超出了 stale-while-revalidate
的时间范围,则它将无法满足浏览器的请求。浏览器将改为从网络中检索响应,并利用该响应满足初始请求,并使用新的响应填充本地缓存。
实时示例
下面是一个简单的 HTTP API 示例,该 API 用于返回当前时间,更具体地说,就是当前这一小时后经过的分钟数。
在这种情况下,网络服务器会在其 HTTP 响应中使用此 Cache-Control
标头:
Cache-Control: max-age=1, stale-while-revalidate=59
此设置意味着,如果针对该时间的请求在接下来的 1 秒内重复出现,则先前缓存的值仍将保持最新状态并原样使用,无需任何重新验证。
如果在 1 到 60 秒后重复发出请求,则缓存的值将过时,但将用于完成 API 请求。同时,“在后台”发出重新验证请求,使用新值填充缓存以供将来使用。
如果请求在超过 60 秒后重复出现,则完全不会使用过时响应,是否完成浏览器请求和缓存重新验证都将依赖于从网络获得响应。
下面对这三种不同状态进行了细分,以及每种状态适用的时间范围:
常见使用场景有哪些?
虽然上述“整点后数分钟”API 服务是人为设计的,但它说明了预期用例,即提供需要刷新的信息,但一定程度的过时也是可以接受的服务。
一些不太人力的示例包括针对当前天气状况的 API,或过去一小时内撰写的头条新闻。
通常,任何以已知时间间隔更新的响应都可能会被多次请求,且在该时间间隔内保持静态,都非常适合通过 max-age
进行短期缓存。将 stale-while-revalidate
与 max-age
结合使用可提高从缓存执行未来请求的可能性,使之能够使用更新的内容执行,而不会阻止网络响应。
它如何与 Service Worker 交互?
如果您听说过 stale-while-revalidate
,那么可能是因为它出现在 Service Worker 中使用的食谱的上下文中。
通过 Cache-Control
标头使用 stale-while-revalidate 方法与它在 Service Worker 中的用法有一些相似之处,并且同样需要注意新鲜度权衡和最长生命周期。不过,在决定是实现基于 Service Worker 的方法时,还是只依赖于 Cache-Control
标头配置时,您应考虑一些注意事项。
在以下情况下,请使用 Service Worker 方法...
- 您已经在 Web 应用中使用 Service Worker。
- 您需要对缓存的内容进行精细控制,并且希望实现一些类似于最近最少使用的到期政策。Workbox 的缓存过期时间模块可为您提供帮助。
- 在重新验证步骤中,您希望在过时响应在后台发生变化时收到通知。Workbox 的广播缓存更新模块可帮助完成此任务。
- 在所有现代浏览器中,您都需要此
stale-while-revalidate
行为。
在以下情况下,请使用 Cache-Control 方法...
- 而不希望为 Web 应用部署和维护 Service Worker 带来的开销。
- 您可以允许浏览器的自动缓存管理防止本地缓存变得过大。
- 您可以采用目前并非所有现代浏览器都支持的方法(从 2019 年 7 月开始支持;未来可能会增加支持的方法)。
如果您使用的是 Service Worker,并且还通过 Cache-Control
标头为某些响应启用了 stale-while-revalidate
,则 Service Worker 通常会“第一次”响应请求。如果 Service Worker 决定不响应,或者在生成响应的过程中使用 fetch()
发出网络请求,那么通过 Cache-Control
标头配置的行为最终将生效。
了解详情
- Fetch API 规范中的
stale-while-revalidate
响应。 - RFC 5861,涵盖初始
stale-while-revalidate
规范。 - HTTP 缓存:您的第一道防线,请参阅本网站上的“网络可靠性”指南。
主打图片:Samuel Zeller。