利用“在重新验证时过时”功能保持内容的新鲜度

另一个工具,可帮助您在提供 Web 应用时平衡即时性和新鲜度。

哪些商品已发货?

stale-while-revalidate 可帮助开发者在即时性(立即加载缓存的内容)与新鲜度(确保将来使用对缓存内容的更新)之间取得平衡。如果您维护的第三方网络服务或库定期更新,或者第一方资产的生命周期往往较短,那么 stale-while-revalidate 可能是对现有缓存政策的补充。

Chrome 75Firefox 68 支持在 Cache-Control 响应标头中设置 stale-while-revalidatemax-age

不支持 stale-while-revalidate 的浏览器会以静默方式忽略该配置值,并使用 max-age,我稍后会加以说明...

这是什么意思?

我们将 stale-while-revalidate 分为两部分:缓存响应可能已过时的概念以及重新验证过程。

首先,浏览器如何知道缓存的响应是否为“过时”?包含 stale-while-revalidateCache-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-revalidatemax-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 标头配置的行为最终将生效。

了解详情

主打图片:Samuel Zeller。