使用缓存条目响应请求时,虽然速度快,但需要权衡用户最终可能会看到过时数据。
workbox-broadcast-update
软件包提供了一种标准方法,用于通知 Window 客户端缓存的响应已更新。此策略最常与 StaleWhileRevalidate
策略结合使用。
每当该策略的“重新验证”步骤从网络中检索到与之前缓存的响应不同的响应时,此模块就会向当前 Service Worker 作用域内的所有窗口客户端发送消息(通过 postMessage()
)。
窗口客户端可以监听更新并执行适当的操作,例如自动向用户显示一条消息,告知他们有可用更新。
如何确定更新?
系统会比较缓存对象和新 Response
对象的某些标头,如果任何标头具有不同的值,则将其视为更新。
默认情况下,系统会比较 Content-Length
、ETag
和 Last-Modified
头文件。
为了提高效率,Workbox 会使用标头值,而不是逐字节比较响应正文,尤其是对于规模可能较大的响应
使用广播更新
该库旨在与 StaleWhileRevalidate
缓存策略一起使用,因为该策略涉及立即返回缓存的响应,但也提供了一种异步更新缓存的机制。
如需广播更新,只需将 broadcastUpdate.BroadcastUpdatePlugin
添加到策略选项中即可。
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
import {BroadcastUpdatePlugin} from 'workbox-broadcast-update';
registerRoute(
({url}) => url.pathname.startsWith('/api/'),
new StaleWhileRevalidate({
plugins: [new BroadcastUpdatePlugin()],
})
);
在 Web 应用中,您可以在 DOMContentLoaded
事件触发之前监听这些事件,如下所示:
navigator.serviceWorker.addEventListener('message', async event => {
// Optional: ensure the message came from workbox-broadcast-update
if (event.data.meta === 'workbox-broadcast-update') {
const {cacheName, updatedURL} = event.data.payload;
// Do something with cacheName and updatedURL.
// For example, get the cached content and update
// the content on the page.
const cache = await caches.open(cacheName);
const updatedResponse = await cache.match(updatedURL);
const updatedText = await updatedResponse.text();
}
});
消息格式
在 Web 应用中调用 message
事件监听器时,event.data
属性将采用以下格式:
{
type: 'CACHE_UPDATED',
meta: 'workbox-broadcast-update',
// The two payload values vary depending on the actual update:
payload: {
cacheName: 'the-cache-name',
updatedURL: 'https://example.com/'
}
}
自定义要检查的标头
您可以通过设置 headersToCheck
属性来自定义要检查的标头。
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
import {BroadcastUpdatePlugin} from 'workbox-broadcast-update';
registerRoute(
({url}) => url.pathname.startsWith('/api/'),
new StaleWhileRevalidate({
plugins: [
new BroadcastUpdatePlugin({
headersToCheck: ['X-My-Custom-Header'],
}),
],
})
);
高级用法
虽然大多数开发者会将 workbox-broadcast-update
用作特定策略的插件(如上所示),但也可以在 Service Worker 代码中使用底层逻辑。
import {BroadcastCacheUpdate} from 'workbox-broadcast-update';
const broadcastUpdate = new BroadcastCacheUpdate({
headersToCheck: ['X-My-Custom-Header'],
});
const cacheName = 'api-cache';
const request = new Request('https://example.com/api');
const cache = await caches.open(cacheName);
const oldResponse = await cache.match(request);
const newResponse = await fetch(request);
broadcastUpdate.notifyIfUpdated({
cacheName,
oldResponse,
newResponse,
request,
);
类型
BroadcastCacheUpdate
当缓存的响应更新时,使用 postMessage()
API 通知所有打开的窗口/标签页。
为了提高效率,系统不会比较底层响应正文,而只会检查特定的响应标头。
属性
-
构造函数
void
使用特定的
channelName
构建 BroadcastCacheUpdate 实例,以便在其上广播消息constructor
函数如下所示:(options?: BroadcastCacheUpdateOptions) => {...}
-
notifyIfUpdated
void
比较两个响应,如果响应不同,则通过
postMessage()
向所有窗口客户端发送消息。两个响应都不能是不透明的。发布的消息采用以下格式(其中,
payload
可通过创建实例时使用的generatePayload
选项进行自定义):{ type: 'CACHE_UPDATED', meta: 'workbox-broadcast-update', payload: { cacheName: 'the-cache-name', updatedURL: 'https://example.com/' } }
notifyIfUpdated
函数如下所示:(options: CacheDidUpdateCallbackParam) => {...}
-
返回
Promise<void>
更新发送后便会解决。
-
BroadcastCacheUpdateOptions
属性
-
headersToCheck
string[] 可选
-
notifyAllClients
布尔值 选填
-
generatePayload
void 可选属性
generatePayload
函数如下所示:(options: CacheDidUpdateCallbackParam) => {...}
-
返回
录制<stringany>
-
BroadcastUpdatePlugin
每当缓存的响应更新时,此插件都会自动广播一条消息。
属性
-
构造函数
void
使用传递的选项构造一个
workbox-broadcast-update.BroadcastUpdate
实例,并在每次调用插件的cacheDidUpdate
回调时调用其notifyIfUpdated
方法。constructor
函数如下所示:(options?: BroadcastCacheUpdateOptions) => {...}
方法
responsesAreSame()
workbox-broadcast-update.responsesAreSame(
firstResponse: Response,
secondResponse: Response,
headersToCheck: string[],
)
在给定两个 Response's
的情况下,比较多个标头值以查看它们是否相同。
参数
-
firstResponse
响应
-
secondResponse
响应
-
headersToCheck
字符串[]
返回
-
boolean