使用插件
在许多情况下,能够在获取和缓存请求和响应时对其进行操作,这是有益的,因为它使您无需编写大量的样板代码即可向服务人员添加其他行为。
Workbox插件允许您通过在请求的生命周期中处理响应和请求来添加其他行为。
开箱即用Workbox提供了许多可以使用的插件,如果您想添加自定义逻辑,则可以实现自己的插件。
Workbox的插件
Workbox提供了下面的插件
-
BackgroundSyncPlugin: 如果网络请求失败,则将其添加到后台同步队列中,并在触发下一个同步事件时重试该请求。
-
BroadcastUpdatePlugin: 无论何时,当一个缓存被更新, 他会通过
postMessage().
派发一个消息 -
CacheableResponsePlugin: 仅缓存满足特定条件的请求
-
ExpirationPlugin: 管理缓存中项目的数量和最长期限。
-
RangeRequestsPlugin: 响应包含Range:响应的header中的部分内容来自于缓存。
通过将实例添加到plugins属性,可以将这些插件与Workbox策略结合使用:
import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';
registerRoute(
({request}) => request.destination === 'image',
new CacheFirst({
cacheName: 'images',
plugins: [
new ExpirationPlugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
}),
],
}),
);
自定义插件
您可以通过传入具有以下任何一种方法的对象来创建自己的插件:
- cacheWillUpdate:在使用Response更新缓存之前调用。您可以在将响应添加到缓存之前更改响应,或者返回null以避免完全更新缓存。
- cacheDidUpdate:在将新条目添加到缓存或更新现有条目时调用。如果希望在缓存更新后执行操作,则很有用。
- cacheKeyWillBeUsed:在将请求用作缓存键之前调用,用于缓存查找(当mode为“read”时)和缓存写入(当mode为“write”时)。如果您需要在使用URL进行缓存访问之前覆盖URL或对其进行规范化,这可能会派上用场。
- cachedResponseWillBeUsed:在使用来自缓存的响应之前调用,此回调可让您检查该响应,并可能返回null或使用其他响应代替。
- requestWillFetch:将要发出网络请求时调用此方法。您可以在此callback中修改请求
- fetchDidFail:当网络请求失败(最有可能是由于NetworkError导致)失败时调用。请注意,当从网络返回带有错误状态的响应(如404 Not Found)时,不会调用此方法。
- fetchDidSucceed:当网络请求成功时调用,无论响应的HTTP状态如何.
- handlerWillStart:在任何处理程序逻辑开始运行之前调用。此回调可用于设置初始处理程序状态(例如记录开始时间).
- handlerWillRespond:在策略handle()方法返回响应之前调用。此回调可用于在将该响应返回到路由处理程序或其他自定义逻辑之前修改该响应。
- handlerDidRespond:在策略的handle()方法返回响应之后调用。此回调可用于记录任何最终响应详细信息,例如在其他plugins提供的响应变更的功能
- handlerDidComplete: 添加到事件的所扩展生命周期的promise均是已解决状态后调用。此回调可用于报告需要等待handler完成以进行计算的任何数据(例如,缓存命中状态,缓存延迟,网络延迟)。。
- handlerDidError:如果处理程序无法提供任意来源的有效响应时调用。此回调可用于提供“后备”内容,以替代网络错误。每当缓存或获取事件到达回调的相关点时,将使用await调用所有这些函数。
每当缓存或获取事件到达回调的时,所有这些函数都将通过await调用。
使用所有这些回调的插件如下所示:
const myPlugin = {
cacheWillUpdate: async ({request, response, event, state}) => {
// Return `response`, a different `Response` object, or `null`.
return response;
},
cacheDidUpdate: async ({cacheName, request, oldResponse, newResponse, event, state}) => {
// No return expected
// Note: `newResponse.bodyUsed` is `true` when this is called,
// meaning the body has already been read. If you need access to
// the body of the fresh response, use a technique like:
// const freshResponse = await caches.match(request, {cacheName});
},
cacheKeyWillBeUsed: async ({request, mode, params, event, state}) => {
// `request` is the `Request` object that would otherwise be used as the cache key.
// `mode` is either 'read' or 'write'.
// Return either a string, or a `Request` whose `url` property will be used as the cache key.
// Returning the original `request` will make this a no-op.
return request;
},
cachedResponseWillBeUsed: async ({cacheName, request, matchOptions, cachedResponse, event, state}) => {
// Return `cachedResponse`, a different `Response` object, or null.
return cachedResponse;
},
requestWillFetch: async ({request, event, state}) => {
// Return `request` or a different `Request` object.
return request;
},
fetchDidFail: async ({originalRequest, request, error, event, state}) => {
// No return expected.
// NOTE: `originalRequest` is the browser's request, `request` is the
// request after being passed through plugins with
// `requestWillFetch` callbacks, and `error` is the exception that caused
// the underlying `fetch()` to fail.
},
fetchDidSucceed: async ({request, response, event, state}) => {
// Return `response` to use the network response as-is,
// or alternatively create and return a new `Response` object.
return response;
},
handlerWillStart: async ({request, event, state}) => {
// No return expected.
// Can set initial handler state here.
},
handlerWillRespond: async ({request, response, event, state}) => {
// Return `response` or a different `Response` object.
return response;
},
handlerDidRespond: async ({request, response, event, state}) => {
// No return expected.
// Can record final response details here.
},
handlerDidComplete: async ({request, response, error, event, state}) => {
// No return expected.
// Can report any data here.
},
handlerDidError: async ({request, event, error, state}) => {
// Return `response`, a different `Response` object as a fallback, or `null`.
return response;
}
};