工作区广播更新

使用缓存条目响应请求时,虽然速度快,但需要权衡用户最终可能会看到过时数据。

workbox-broadcast-update 软件包提供了一种标准方法,用于通知 Window 客户端缓存的响应已更新。此策略最常与 StaleWhileRevalidate 策略结合使用。

每当该策略的“重新验证”步骤从网络中检索到与之前缓存的响应不同的响应时,此模块就会向当前 Service Worker 作用域内的所有窗口客户端发送消息(通过 postMessage())。

窗口客户端可以监听更新并执行适当的操作,例如自动向用户显示一条消息,告知他们有可用更新。

如何确定更新?

系统会比较缓存对象和新 Response 对象的某些标头,如果任何标头具有不同的值,则将其视为更新。

默认情况下,系统会比较 Content-LengthETagLast-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

属性

BroadcastUpdatePlugin

每当缓存的响应更新时,此插件都会自动广播一条消息。

属性

方法

responsesAreSame()

workbox-broadcast-update.responsesAreSame(
  firstResponse: Response,
  secondResponse: Response,
  headersToCheck: string[],
)

在给定两个 Response's 的情况下,比较多个标头值以查看它们是否相同。

参数

  • firstResponse

    响应

  • secondResponse

    响应

  • headersToCheck

    字符串[]

返回

  • boolean