这是一个额外的工具,可帮助您在分发 Web 应用时平衡即时性和新鲜度。
哪些商品已发货?
stale-while-revalidate
可帮助开发者在即时性(立即加载缓存的内容)和新鲜度(确保将来使用缓存内容的更新)之间取得平衡。如果您维护的第三方 Web 服务或库会定期更新,或者您的第一方素材资源通常具有较短的生命周期,那么 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 示例,用于返回当前时间,更具体地说,是当前小时过后的分钟数。
在这种情况下,Web 服务器会在其 HTTP 响应中使用此 Cache-Control
标头:
Cache-Control: max-age=1, stale-while-revalidate=59
此设置表示,如果在接下来的 1 秒内重复请求时间,之前缓存的值仍会保持新鲜状态,并按原样使用,而无需任何重新验证。
如果在 1 到 60 秒后重复发出请求,则缓存的值将过时,但仍会用于执行 API 请求。与此同时,“在后台”,系统会发出重新验证请求,以便使用新值填充缓存以供日后使用。
如果在 60 秒后重复请求,则系统不会使用过时响应,并且满足浏览器请求和缓存重新验证都将取决于从网络获取响应。
下面详细介绍了这三种不同的状态,以及在我们的示例中每种状态适用的时间范围:
常见用例有哪些?
虽然上面的“小时过后几分钟”API 服务示例是人为构建的,但它说明了预期的用例:提供需要刷新的信息,但可以接受一定程度的过时信息的服务。
不那么牵强附会的示例可能是当前天气状况的 API,或过去一小时内撰写的头条新闻。
通常,任何以已知间隔更新、可能会被多次请求且在该间隔内保持静态的响应都非常适合通过 max-age
进行短期缓存。除了 max-age
之外,使用 stale-while-revalidate
有助于提高从缓存中使用更新内容来满足未来请求的可能性,而不会阻塞网络响应。
它如何与 Service Worker 交互?
如果您听说过 stale-while-revalidate
,很可能是在 服务工件中使用的食谱的上下文中。
通过 Cache-Control
标头使用“在重新验证期间使用过时数据”与在服务工件中使用该功能有许多相似之处,并且关于新鲜度权衡和最大生命周期的许多注意事项也适用。不过,在决定是实现基于服务工件的方案,还是仅依赖 Cache-Control
标头配置时,您需要考虑以下几点。
在以下情况下,请使用服务工件方法:
- 您已在 Web 应用中使用 Service Worker。
- 您需要对缓存内容进行精细控制,并希望实现类似于最近最少使用过期政策的功能。Workbox 的缓存过期时间模块可以帮助您解决此问题。
- 您希望在重新验证步骤中,当过时响应在后台发生更改时收到通知。Workbox 的广播缓存更新模块可以帮助实现这一点。
- 您需要在所有现代浏览器中实现此
stale-while-revalidate
行为。
在以下情况下,请使用 Cache-Control 方法:
- 您不想处理为 Web 应用部署和维护 Service Worker 的开销。
- 您可以让浏览器的自动缓存管理功能防止本地缓存过大。
- 您可以接受目前并非所有现代浏览器都支持的方法(截至 2019 年 7 月;未来可能会增加支持的方法)。
如果您使用的是 Service Worker,并且还通过 Cache-Control
标头为某些响应启用了 stale-while-revalidate
,那么通常情况下,Service Worker 将有机会先响应请求。如果服务工件决定不响应,或者在生成响应过程中使用 fetch()
发出网络请求,则最终会采用通过 Cache-Control
标头配置的行为。
了解详情
- Fetch API 规范中的
stale-while-revalidate
响应。 - RFC 5861,介绍了初始的
stale-while-revalidate
规范。 - HTTP 缓存:您的第一道防线,来自本网站上的“网络可靠性”指南。
主打图片由 Samuel Zeller 提供。