123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- /*
- Copyright 2018 Google LLC
- Use of this source code is governed by an MIT-style
- license that can be found in the LICENSE file or at
- https://opensource.org/licenses/MIT.
- */
- import { assert } from 'workbox-core/_private/assert.js';
- import { logger } from 'workbox-core/_private/logger.js';
- import { WorkboxError } from 'workbox-core/_private/WorkboxError.js';
- import { cacheOkAndOpaquePlugin } from './plugins/cacheOkAndOpaquePlugin.js';
- import { Strategy } from './Strategy.js';
- import { messages } from './utils/messages.js';
- import './_version.js';
- /**
- * An implementation of a
- * [stale-while-revalidate]{@link https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#stale-while-revalidate}
- * request strategy.
- *
- * Resources are requested from both the cache and the network in parallel.
- * The strategy will respond with the cached version if available, otherwise
- * wait for the network response. The cache is updated with the network response
- * with each successful request.
- *
- * By default, this strategy will cache responses with a 200 status code as
- * well as [opaque responses]{@link https://developers.google.com/web/tools/workbox/guides/handle-third-party-requests}.
- * Opaque responses are cross-origin requests where the response doesn't
- * support [CORS]{@link https://enable-cors.org/}.
- *
- * If the network request fails, and there is no cache match, this will throw
- * a `WorkboxError` exception.
- *
- * @extends module:workbox-strategies.Strategy
- * @memberof module:workbox-strategies
- */
- class StaleWhileRevalidate extends Strategy {
- /**
- * @param {Object} [options]
- * @param {string} [options.cacheName] Cache name to store and retrieve
- * requests. Defaults to cache names provided by
- * [workbox-core]{@link module:workbox-core.cacheNames}.
- * @param {Array<Object>} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}
- * to use in conjunction with this caching strategy.
- * @param {Object} [options.fetchOptions] Values passed along to the
- * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
- * of [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796)
- * `fetch()` requests made by this strategy.
- * @param {Object} [options.matchOptions] [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions)
- */
- constructor(options = {}) {
- super(options);
- // If this instance contains no plugins with a 'cacheWillUpdate' callback,
- // prepend the `cacheOkAndOpaquePlugin` plugin to the plugins list.
- if (!this.plugins.some((p) => 'cacheWillUpdate' in p)) {
- this.plugins.unshift(cacheOkAndOpaquePlugin);
- }
- }
- /**
- * @private
- * @param {Request|string} request A request to run this strategy for.
- * @param {module:workbox-strategies.StrategyHandler} handler The event that
- * triggered the request.
- * @return {Promise<Response>}
- */
- async _handle(request, handler) {
- const logs = [];
- if (process.env.NODE_ENV !== 'production') {
- assert.isInstance(request, Request, {
- moduleName: 'workbox-strategies',
- className: this.constructor.name,
- funcName: 'handle',
- paramName: 'request',
- });
- }
- const fetchAndCachePromise = handler.fetchAndCachePut(request).catch(() => {
- // Swallow this error because a 'no-response' error will be thrown in
- // main handler return flow. This will be in the `waitUntil()` flow.
- });
- let response = await handler.cacheMatch(request);
- let error;
- if (response) {
- if (process.env.NODE_ENV !== 'production') {
- logs.push(`Found a cached response in the '${this.cacheName}'` +
- ` cache. Will update with the network response in the background.`);
- }
- }
- else {
- if (process.env.NODE_ENV !== 'production') {
- logs.push(`No response found in the '${this.cacheName}' cache. ` +
- `Will wait for the network response.`);
- }
- try {
- // NOTE(philipwalton): Really annoying that we have to type cast here.
- // https://github.com/microsoft/TypeScript/issues/20006
- response = (await fetchAndCachePromise);
- }
- catch (err) {
- if (err instanceof Error) {
- error = err;
- }
- }
- }
- if (process.env.NODE_ENV !== 'production') {
- logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));
- for (const log of logs) {
- logger.log(log);
- }
- messages.printFinalResponse(response);
- logger.groupEnd();
- }
- if (!response) {
- throw new WorkboxError('no-response', { url: request.url, error });
- }
- return response;
- }
- }
- export { StaleWhileRevalidate };
|