1 | this.workbox = this.workbox || {};
|
2 | this.workbox.strategies = (function (exports, logger_mjs, assert_mjs, cacheNames_mjs, cacheWrapper_mjs, fetchWrapper_mjs, getFriendlyURL_mjs, WorkboxError_mjs) {
|
3 | ;
|
4 |
|
5 | try {
|
6 | self['workbox:strategies:4.1.1'] && _();
|
7 | } catch (e) {} // eslint-disable-line
|
8 |
|
9 | /*
|
10 | Copyright 2018 Google LLC
|
11 |
|
12 | Use of this source code is governed by an MIT-style
|
13 | license that can be found in the LICENSE file or at
|
14 | https://opensource.org/licenses/MIT.
|
15 | */
|
16 |
|
17 | const getFriendlyURL = url => {
|
18 | const urlObj = new URL(url, location);
|
19 |
|
20 | if (urlObj.origin === location.origin) {
|
21 | return urlObj.pathname;
|
22 | }
|
23 |
|
24 | return urlObj.href;
|
25 | };
|
26 |
|
27 | const messages = {
|
28 | strategyStart: (strategyName, request) => `Using ${strategyName} to ` + `respond to '${getFriendlyURL(request.url)}'`,
|
29 | printFinalResponse: response => {
|
30 | if (response) {
|
31 | logger_mjs.logger.groupCollapsed(`View the final response here.`);
|
32 | logger_mjs.logger.log(response);
|
33 | logger_mjs.logger.groupEnd();
|
34 | }
|
35 | }
|
36 | };
|
37 |
|
38 | /*
|
39 | Copyright 2018 Google LLC
|
40 |
|
41 | Use of this source code is governed by an MIT-style
|
42 | license that can be found in the LICENSE file or at
|
43 | https://opensource.org/licenses/MIT.
|
44 | */
|
45 | /**
|
46 | * An implementation of a [cache-first]{@link https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-falling-back-to-network}
|
47 | * request strategy.
|
48 | *
|
49 | * A cache first strategy is useful for assets that have been revisioned,
|
50 | * such as URLs like `/styles/example.a8f5f1.css`, since they
|
51 | * can be cached for long periods of time.
|
52 | *
|
53 | * If the network request fails, and there is no cache match, this will throw
|
54 | * a `WorkboxError` exception.
|
55 | *
|
56 | * @memberof workbox.strategies
|
57 | */
|
58 |
|
59 | class CacheFirst {
|
60 | /**
|
61 | * @param {Object} options
|
62 | * @param {string} options.cacheName Cache name to store and retrieve
|
63 | * requests. Defaults to cache names provided by
|
64 | * [workbox-core]{@link workbox.core.cacheNames}.
|
65 | * @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}
|
66 | * to use in conjunction with this caching strategy.
|
67 | * @param {Object} options.fetchOptions Values passed along to the
|
68 | * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
|
69 | * of all fetch() requests made by this strategy.
|
70 | * @param {Object} options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions)
|
71 | */
|
72 | constructor(options = {}) {
|
73 | this._cacheName = cacheNames_mjs.cacheNames.getRuntimeName(options.cacheName);
|
74 | this._plugins = options.plugins || [];
|
75 | this._fetchOptions = options.fetchOptions || null;
|
76 | this._matchOptions = options.matchOptions || null;
|
77 | }
|
78 | /**
|
79 | * This method will perform a request strategy and follows an API that
|
80 | * will work with the
|
81 | * [Workbox Router]{@link workbox.routing.Router}.
|
82 | *
|
83 | * @param {Object} options
|
84 | * @param {Request} options.request The request to run this strategy for.
|
85 | * @param {Event} [options.event] The event that triggered the request.
|
86 | * @return {Promise<Response>}
|
87 | */
|
88 |
|
89 |
|
90 | async handle({
|
91 | event,
|
92 | request
|
93 | }) {
|
94 | return this.makeRequest({
|
95 | event,
|
96 | request: request || event.request
|
97 | });
|
98 | }
|
99 | /**
|
100 | * This method can be used to perform a make a standalone request outside the
|
101 | * context of the [Workbox Router]{@link workbox.routing.Router}.
|
102 | *
|
103 | * See "[Advanced Recipes](https://developers.google.com/web/tools/workbox/guides/advanced-recipes#make-requests)"
|
104 | * for more usage information.
|
105 | *
|
106 | * @param {Object} options
|
107 | * @param {Request|string} options.request Either a
|
108 | * [`Request`]{@link https://developer.mozilla.org/en-US/docs/Web/API/Request}
|
109 | * object, or a string URL, corresponding to the request to be made.
|
110 | * @param {FetchEvent} [options.event] If provided, `event.waitUntil()` will
|
111 | be called automatically to extend the service worker's lifetime.
|
112 | * @return {Promise<Response>}
|
113 | */
|
114 |
|
115 |
|
116 | async makeRequest({
|
117 | event,
|
118 | request
|
119 | }) {
|
120 | const logs = [];
|
121 |
|
122 | if (typeof request === 'string') {
|
123 | request = new Request(request);
|
124 | }
|
125 |
|
126 | {
|
127 | assert_mjs.assert.isInstance(request, Request, {
|
128 | moduleName: 'workbox-strategies',
|
129 | className: 'CacheFirst',
|
130 | funcName: 'makeRequest',
|
131 | paramName: 'request'
|
132 | });
|
133 | }
|
134 |
|
135 | let response = await cacheWrapper_mjs.cacheWrapper.match({
|
136 | cacheName: this._cacheName,
|
137 | request,
|
138 | event,
|
139 | matchOptions: this._matchOptions,
|
140 | plugins: this._plugins
|
141 | });
|
142 | let error;
|
143 |
|
144 | if (!response) {
|
145 | {
|
146 | logs.push(`No response found in the '${this._cacheName}' cache. ` + `Will respond with a network request.`);
|
147 | }
|
148 |
|
149 | try {
|
150 | response = await this._getFromNetwork(request, event);
|
151 | } catch (err) {
|
152 | error = err;
|
153 | }
|
154 |
|
155 | {
|
156 | if (response) {
|
157 | logs.push(`Got response from network.`);
|
158 | } else {
|
159 | logs.push(`Unable to get a response from the network.`);
|
160 | }
|
161 | }
|
162 | } else {
|
163 | {
|
164 | logs.push(`Found a cached response in the '${this._cacheName}' cache.`);
|
165 | }
|
166 | }
|
167 |
|
168 | {
|
169 | logger_mjs.logger.groupCollapsed(messages.strategyStart('CacheFirst', request));
|
170 |
|
171 | for (let log of logs) {
|
172 | logger_mjs.logger.log(log);
|
173 | }
|
174 |
|
175 | messages.printFinalResponse(response);
|
176 | logger_mjs.logger.groupEnd();
|
177 | }
|
178 |
|
179 | if (!response) {
|
180 | throw new WorkboxError_mjs.WorkboxError('no-response', {
|
181 | url: request.url,
|
182 | error
|
183 | });
|
184 | }
|
185 |
|
186 | return response;
|
187 | }
|
188 | /**
|
189 | * Handles the network and cache part of CacheFirst.
|
190 | *
|
191 | * @param {Request} request
|
192 | * @param {FetchEvent} [event]
|
193 | * @return {Promise<Response>}
|
194 | *
|
195 | * @private
|
196 | */
|
197 |
|
198 |
|
199 | async _getFromNetwork(request, event) {
|
200 | const response = await fetchWrapper_mjs.fetchWrapper.fetch({
|
201 | request,
|
202 | event,
|
203 | fetchOptions: this._fetchOptions,
|
204 | plugins: this._plugins
|
205 | }); // Keep the service worker while we put the request to the cache
|
206 |
|
207 | const responseClone = response.clone();
|
208 | const cachePutPromise = cacheWrapper_mjs.cacheWrapper.put({
|
209 | cacheName: this._cacheName,
|
210 | request,
|
211 | response: responseClone,
|
212 | event,
|
213 | plugins: this._plugins
|
214 | });
|
215 |
|
216 | if (event) {
|
217 | try {
|
218 | event.waitUntil(cachePutPromise);
|
219 | } catch (error) {
|
220 | {
|
221 | logger_mjs.logger.warn(`Unable to ensure service worker stays alive when ` + `updating cache for '${getFriendlyURL_mjs.getFriendlyURL(request.url)}'.`);
|
222 | }
|
223 | }
|
224 | }
|
225 |
|
226 | return response;
|
227 | }
|
228 |
|
229 | }
|
230 |
|
231 | /*
|
232 | Copyright 2018 Google LLC
|
233 |
|
234 | Use of this source code is governed by an MIT-style
|
235 | license that can be found in the LICENSE file or at
|
236 | https://opensource.org/licenses/MIT.
|
237 | */
|
238 | /**
|
239 | * An implementation of a
|
240 | * [cache-only]{@link https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-only}
|
241 | * request strategy.
|
242 | *
|
243 | * This class is useful if you want to take advantage of any
|
244 | * [Workbox plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}.
|
245 | *
|
246 | * If there is no cache match, this will throw a `WorkboxError` exception.
|
247 | *
|
248 | * @memberof workbox.strategies
|
249 | */
|
250 |
|
251 | class CacheOnly {
|
252 | /**
|
253 | * @param {Object} options
|
254 | * @param {string} options.cacheName Cache name to store and retrieve
|
255 | * requests. Defaults to cache names provided by
|
256 | * [workbox-core]{@link workbox.core.cacheNames}.
|
257 | * @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}
|
258 | * to use in conjunction with this caching strategy.
|
259 | * @param {Object} options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions)
|
260 | */
|
261 | constructor(options = {}) {
|
262 | this._cacheName = cacheNames_mjs.cacheNames.getRuntimeName(options.cacheName);
|
263 | this._plugins = options.plugins || [];
|
264 | this._matchOptions = options.matchOptions || null;
|
265 | }
|
266 | /**
|
267 | * This method will perform a request strategy and follows an API that
|
268 | * will work with the
|
269 | * [Workbox Router]{@link workbox.routing.Router}.
|
270 | *
|
271 | * @param {Object} options
|
272 | * @param {Request} options.request The request to run this strategy for.
|
273 | * @param {Event} [options.event] The event that triggered the request.
|
274 | * @return {Promise<Response>}
|
275 | */
|
276 |
|
277 |
|
278 | async handle({
|
279 | event,
|
280 | request
|
281 | }) {
|
282 | return this.makeRequest({
|
283 | event,
|
284 | request: request || event.request
|
285 | });
|
286 | }
|
287 | /**
|
288 | * This method can be used to perform a make a standalone request outside the
|
289 | * context of the [Workbox Router]{@link workbox.routing.Router}.
|
290 | *
|
291 | * See "[Advanced Recipes](https://developers.google.com/web/tools/workbox/guides/advanced-recipes#make-requests)"
|
292 | * for more usage information.
|
293 | *
|
294 | * @param {Object} options
|
295 | * @param {Request|string} options.request Either a
|
296 | * [`Request`]{@link https://developer.mozilla.org/en-US/docs/Web/API/Request}
|
297 | * object, or a string URL, corresponding to the request to be made.
|
298 | * @param {FetchEvent} [options.event] If provided, `event.waitUntil()` will
|
299 | * be called automatically to extend the service worker's lifetime.
|
300 | * @return {Promise<Response>}
|
301 | */
|
302 |
|
303 |
|
304 | async makeRequest({
|
305 | event,
|
306 | request
|
307 | }) {
|
308 | if (typeof request === 'string') {
|
309 | request = new Request(request);
|
310 | }
|
311 |
|
312 | {
|
313 | assert_mjs.assert.isInstance(request, Request, {
|
314 | moduleName: 'workbox-strategies',
|
315 | className: 'CacheOnly',
|
316 | funcName: 'makeRequest',
|
317 | paramName: 'request'
|
318 | });
|
319 | }
|
320 |
|
321 | const response = await cacheWrapper_mjs.cacheWrapper.match({
|
322 | cacheName: this._cacheName,
|
323 | request,
|
324 | event,
|
325 | matchOptions: this._matchOptions,
|
326 | plugins: this._plugins
|
327 | });
|
328 |
|
329 | {
|
330 | logger_mjs.logger.groupCollapsed(messages.strategyStart('CacheOnly', request));
|
331 |
|
332 | if (response) {
|
333 | logger_mjs.logger.log(`Found a cached response in the '${this._cacheName}'` + ` cache.`);
|
334 | messages.printFinalResponse(response);
|
335 | } else {
|
336 | logger_mjs.logger.log(`No response found in the '${this._cacheName}' cache.`);
|
337 | }
|
338 |
|
339 | logger_mjs.logger.groupEnd();
|
340 | }
|
341 |
|
342 | if (!response) {
|
343 | throw new WorkboxError_mjs.WorkboxError('no-response', {
|
344 | url: request.url
|
345 | });
|
346 | }
|
347 |
|
348 | return response;
|
349 | }
|
350 |
|
351 | }
|
352 |
|
353 | /*
|
354 | Copyright 2018 Google LLC
|
355 |
|
356 | Use of this source code is governed by an MIT-style
|
357 | license that can be found in the LICENSE file or at
|
358 | https://opensource.org/licenses/MIT.
|
359 | */
|
360 | const cacheOkAndOpaquePlugin = {
|
361 | /**
|
362 | * Returns a valid response (to allow caching) if the status is 200 (OK) or
|
363 | * 0 (opaque).
|
364 | *
|
365 | * @param {Object} options
|
366 | * @param {Response} options.response
|
367 | * @return {Response|null}
|
368 | *
|
369 | * @private
|
370 | */
|
371 | cacheWillUpdate: ({
|
372 | response
|
373 | }) => {
|
374 | if (response.status === 200 || response.status === 0) {
|
375 | return response;
|
376 | }
|
377 |
|
378 | return null;
|
379 | }
|
380 | };
|
381 |
|
382 | /*
|
383 | Copyright 2018 Google LLC
|
384 |
|
385 | Use of this source code is governed by an MIT-style
|
386 | license that can be found in the LICENSE file or at
|
387 | https://opensource.org/licenses/MIT.
|
388 | */
|
389 | /**
|
390 | * An implementation of a
|
391 | * [network first]{@link https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#network-falling-back-to-cache}
|
392 | * request strategy.
|
393 | *
|
394 | * By default, this strategy will cache responses with a 200 status code as
|
395 | * well as [opaque responses]{@link https://developers.google.com/web/tools/workbox/guides/handle-third-party-requests}.
|
396 | * Opaque responses are are cross-origin requests where the response doesn't
|
397 | * support [CORS]{@link https://enable-cors.org/}.
|
398 | *
|
399 | * If the network request fails, and there is no cache match, this will throw
|
400 | * a `WorkboxError` exception.
|
401 | *
|
402 | * @memberof workbox.strategies
|
403 | */
|
404 |
|
405 | class NetworkFirst {
|
406 | /**
|
407 | * @param {Object} options
|
408 | * @param {string} options.cacheName Cache name to store and retrieve
|
409 | * requests. Defaults to cache names provided by
|
410 | * [workbox-core]{@link workbox.core.cacheNames}.
|
411 | * @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}
|
412 | * to use in conjunction with this caching strategy.
|
413 | * @param {Object} options.fetchOptions Values passed along to the
|
414 | * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
|
415 | * of all fetch() requests made by this strategy.
|
416 | * @param {Object} options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions)
|
417 | * @param {number} options.networkTimeoutSeconds If set, any network requests
|
418 | * that fail to respond within the timeout will fallback to the cache.
|
419 | *
|
420 | * This option can be used to combat
|
421 | * "[lie-fi]{@link https://developers.google.com/web/fundamentals/performance/poor-connectivity/#lie-fi}"
|
422 | * scenarios.
|
423 | */
|
424 | constructor(options = {}) {
|
425 | this._cacheName = cacheNames_mjs.cacheNames.getRuntimeName(options.cacheName);
|
426 |
|
427 | if (options.plugins) {
|
428 | let isUsingCacheWillUpdate = options.plugins.some(plugin => !!plugin.cacheWillUpdate);
|
429 | this._plugins = isUsingCacheWillUpdate ? options.plugins : [cacheOkAndOpaquePlugin, ...options.plugins];
|
430 | } else {
|
431 | // No plugins passed in, use the default plugin.
|
432 | this._plugins = [cacheOkAndOpaquePlugin];
|
433 | }
|
434 |
|
435 | this._networkTimeoutSeconds = options.networkTimeoutSeconds;
|
436 |
|
437 | {
|
438 | if (this._networkTimeoutSeconds) {
|
439 | assert_mjs.assert.isType(this._networkTimeoutSeconds, 'number', {
|
440 | moduleName: 'workbox-strategies',
|
441 | className: 'NetworkFirst',
|
442 | funcName: 'constructor',
|
443 | paramName: 'networkTimeoutSeconds'
|
444 | });
|
445 | }
|
446 | }
|
447 |
|
448 | this._fetchOptions = options.fetchOptions || null;
|
449 | this._matchOptions = options.matchOptions || null;
|
450 | }
|
451 | /**
|
452 | * This method will perform a request strategy and follows an API that
|
453 | * will work with the
|
454 | * [Workbox Router]{@link workbox.routing.Router}.
|
455 | *
|
456 | * @param {Object} options
|
457 | * @param {Request} options.request The request to run this strategy for.
|
458 | * @param {Event} [options.event] The event that triggered the request.
|
459 | * @return {Promise<Response>}
|
460 | */
|
461 |
|
462 |
|
463 | async handle({
|
464 | event,
|
465 | request
|
466 | }) {
|
467 | return this.makeRequest({
|
468 | event,
|
469 | request: request || event.request
|
470 | });
|
471 | }
|
472 | /**
|
473 | * This method can be used to perform a make a standalone request outside the
|
474 | * context of the [Workbox Router]{@link workbox.routing.Router}.
|
475 | *
|
476 | * See "[Advanced Recipes](https://developers.google.com/web/tools/workbox/guides/advanced-recipes#make-requests)"
|
477 | * for more usage information.
|
478 | *
|
479 | * @param {Object} options
|
480 | * @param {Request|string} options.request Either a
|
481 | * [`Request`]{@link https://developer.mozilla.org/en-US/docs/Web/API/Request}
|
482 | * object, or a string URL, corresponding to the request to be made.
|
483 | * @param {FetchEvent} [options.event] If provided, `event.waitUntil()` will
|
484 | * be called automatically to extend the service worker's lifetime.
|
485 | * @return {Promise<Response>}
|
486 | */
|
487 |
|
488 |
|
489 | async makeRequest({
|
490 | event,
|
491 | request
|
492 | }) {
|
493 | const logs = [];
|
494 |
|
495 | if (typeof request === 'string') {
|
496 | request = new Request(request);
|
497 | }
|
498 |
|
499 | {
|
500 | assert_mjs.assert.isInstance(request, Request, {
|
501 | moduleName: 'workbox-strategies',
|
502 | className: 'NetworkFirst',
|
503 | funcName: 'handle',
|
504 | paramName: 'makeRequest'
|
505 | });
|
506 | }
|
507 |
|
508 | const promises = [];
|
509 | let timeoutId;
|
510 |
|
511 | if (this._networkTimeoutSeconds) {
|
512 | const {
|
513 | id,
|
514 | promise
|
515 | } = this._getTimeoutPromise({
|
516 | request,
|
517 | event,
|
518 | logs
|
519 | });
|
520 |
|
521 | timeoutId = id;
|
522 | promises.push(promise);
|
523 | }
|
524 |
|
525 | const networkPromise = this._getNetworkPromise({
|
526 | timeoutId,
|
527 | request,
|
528 | event,
|
529 | logs
|
530 | });
|
531 |
|
532 | promises.push(networkPromise); // Promise.race() will resolve as soon as the first promise resolves.
|
533 |
|
534 | let response = await Promise.race(promises); // If Promise.race() resolved with null, it might be due to a network
|
535 | // timeout + a cache miss. If that were to happen, we'd rather wait until
|
536 | // the networkPromise resolves instead of returning null.
|
537 | // Note that it's fine to await an already-resolved promise, so we don't
|
538 | // have to check to see if it's still "in flight".
|
539 |
|
540 | if (!response) {
|
541 | response = await networkPromise;
|
542 | }
|
543 |
|
544 | {
|
545 | logger_mjs.logger.groupCollapsed(messages.strategyStart('NetworkFirst', request));
|
546 |
|
547 | for (let log of logs) {
|
548 | logger_mjs.logger.log(log);
|
549 | }
|
550 |
|
551 | messages.printFinalResponse(response);
|
552 | logger_mjs.logger.groupEnd();
|
553 | }
|
554 |
|
555 | if (!response) {
|
556 | throw new WorkboxError_mjs.WorkboxError('no-response', {
|
557 | url: request.url
|
558 | });
|
559 | }
|
560 |
|
561 | return response;
|
562 | }
|
563 | /**
|
564 | * @param {Object} options
|
565 | * @param {Request} options.request
|
566 | * @param {Array} options.logs A reference to the logs array
|
567 | * @param {Event} [options.event]
|
568 | * @return {Promise<Response>}
|
569 | *
|
570 | * @private
|
571 | */
|
572 |
|
573 |
|
574 | _getTimeoutPromise({
|
575 | request,
|
576 | logs,
|
577 | event
|
578 | }) {
|
579 | let timeoutId;
|
580 | const timeoutPromise = new Promise(resolve => {
|
581 | const onNetworkTimeout = async () => {
|
582 | {
|
583 | logs.push(`Timing out the network response at ` + `${this._networkTimeoutSeconds} seconds.`);
|
584 | }
|
585 |
|
586 | resolve((await this._respondFromCache({
|
587 | request,
|
588 | event
|
589 | })));
|
590 | };
|
591 |
|
592 | timeoutId = setTimeout(onNetworkTimeout, this._networkTimeoutSeconds * 1000);
|
593 | });
|
594 | return {
|
595 | promise: timeoutPromise,
|
596 | id: timeoutId
|
597 | };
|
598 | }
|
599 | /**
|
600 | * @param {Object} options
|
601 | * @param {number|undefined} options.timeoutId
|
602 | * @param {Request} options.request
|
603 | * @param {Array} options.logs A reference to the logs Array.
|
604 | * @param {Event} [options.event]
|
605 | * @return {Promise<Response>}
|
606 | *
|
607 | * @private
|
608 | */
|
609 |
|
610 |
|
611 | async _getNetworkPromise({
|
612 | timeoutId,
|
613 | request,
|
614 | logs,
|
615 | event
|
616 | }) {
|
617 | let error;
|
618 | let response;
|
619 |
|
620 | try {
|
621 | response = await fetchWrapper_mjs.fetchWrapper.fetch({
|
622 | request,
|
623 | event,
|
624 | fetchOptions: this._fetchOptions,
|
625 | plugins: this._plugins
|
626 | });
|
627 | } catch (err) {
|
628 | error = err;
|
629 | }
|
630 |
|
631 | if (timeoutId) {
|
632 | clearTimeout(timeoutId);
|
633 | }
|
634 |
|
635 | {
|
636 | if (response) {
|
637 | logs.push(`Got response from network.`);
|
638 | } else {
|
639 | logs.push(`Unable to get a response from the network. Will respond ` + `with a cached response.`);
|
640 | }
|
641 | }
|
642 |
|
643 | if (error || !response) {
|
644 | response = await this._respondFromCache({
|
645 | request,
|
646 | event
|
647 | });
|
648 |
|
649 | {
|
650 | if (response) {
|
651 | logs.push(`Found a cached response in the '${this._cacheName}'` + ` cache.`);
|
652 | } else {
|
653 | logs.push(`No response found in the '${this._cacheName}' cache.`);
|
654 | }
|
655 | }
|
656 | } else {
|
657 | // Keep the service worker alive while we put the request in the cache
|
658 | const responseClone = response.clone();
|
659 | const cachePut = cacheWrapper_mjs.cacheWrapper.put({
|
660 | cacheName: this._cacheName,
|
661 | request,
|
662 | response: responseClone,
|
663 | event,
|
664 | plugins: this._plugins
|
665 | });
|
666 |
|
667 | if (event) {
|
668 | try {
|
669 | // The event has been responded to so we can keep the SW alive to
|
670 | // respond to the request
|
671 | event.waitUntil(cachePut);
|
672 | } catch (err) {
|
673 | {
|
674 | logger_mjs.logger.warn(`Unable to ensure service worker stays alive when ` + `updating cache for '${getFriendlyURL_mjs.getFriendlyURL(request.url)}'.`);
|
675 | }
|
676 | }
|
677 | }
|
678 | }
|
679 |
|
680 | return response;
|
681 | }
|
682 | /**
|
683 | * Used if the network timeouts or fails to make the request.
|
684 | *
|
685 | * @param {Object} options
|
686 | * @param {Request} request The request to match in the cache
|
687 | * @param {Event} [options.event]
|
688 | * @return {Promise<Object>}
|
689 | *
|
690 | * @private
|
691 | */
|
692 |
|
693 |
|
694 | _respondFromCache({
|
695 | event,
|
696 | request
|
697 | }) {
|
698 | return cacheWrapper_mjs.cacheWrapper.match({
|
699 | cacheName: this._cacheName,
|
700 | request,
|
701 | event,
|
702 | matchOptions: this._matchOptions,
|
703 | plugins: this._plugins
|
704 | });
|
705 | }
|
706 |
|
707 | }
|
708 |
|
709 | /*
|
710 | Copyright 2018 Google LLC
|
711 |
|
712 | Use of this source code is governed by an MIT-style
|
713 | license that can be found in the LICENSE file or at
|
714 | https://opensource.org/licenses/MIT.
|
715 | */
|
716 | /**
|
717 | * An implementation of a
|
718 | * [network-only]{@link https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#network-only}
|
719 | * request strategy.
|
720 | *
|
721 | * This class is useful if you want to take advantage of any
|
722 | * [Workbox plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}.
|
723 | *
|
724 | * If the network request fails, this will throw a `WorkboxError` exception.
|
725 | *
|
726 | * @memberof workbox.strategies
|
727 | */
|
728 |
|
729 | class NetworkOnly {
|
730 | /**
|
731 | * @param {Object} options
|
732 | * @param {string} options.cacheName Cache name to store and retrieve
|
733 | * requests. Defaults to cache names provided by
|
734 | * [workbox-core]{@link workbox.core.cacheNames}.
|
735 | * @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}
|
736 | * to use in conjunction with this caching strategy.
|
737 | * @param {Object} options.fetchOptions Values passed along to the
|
738 | * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
|
739 | * of all fetch() requests made by this strategy.
|
740 | */
|
741 | constructor(options = {}) {
|
742 | this._cacheName = cacheNames_mjs.cacheNames.getRuntimeName(options.cacheName);
|
743 | this._plugins = options.plugins || [];
|
744 | this._fetchOptions = options.fetchOptions || null;
|
745 | }
|
746 | /**
|
747 | * This method will perform a request strategy and follows an API that
|
748 | * will work with the
|
749 | * [Workbox Router]{@link workbox.routing.Router}.
|
750 | *
|
751 | * @param {Object} options
|
752 | * @param {Request} options.request The request to run this strategy for.
|
753 | * @param {Event} [options.event] The event that triggered the request.
|
754 | * @return {Promise<Response>}
|
755 | */
|
756 |
|
757 |
|
758 | async handle({
|
759 | event,
|
760 | request
|
761 | }) {
|
762 | return this.makeRequest({
|
763 | event,
|
764 | request: request || event.request
|
765 | });
|
766 | }
|
767 | /**
|
768 | * This method can be used to perform a make a standalone request outside the
|
769 | * context of the [Workbox Router]{@link workbox.routing.Router}.
|
770 | *
|
771 | * See "[Advanced Recipes](https://developers.google.com/web/tools/workbox/guides/advanced-recipes#make-requests)"
|
772 | * for more usage information.
|
773 | *
|
774 | * @param {Object} options
|
775 | * @param {Request|string} options.request Either a
|
776 | * [`Request`]{@link https://developer.mozilla.org/en-US/docs/Web/API/Request}
|
777 | * object, or a string URL, corresponding to the request to be made.
|
778 | * @param {FetchEvent} [options.event] If provided, `event.waitUntil()` will
|
779 | * be called automatically to extend the service worker's lifetime.
|
780 | * @return {Promise<Response>}
|
781 | */
|
782 |
|
783 |
|
784 | async makeRequest({
|
785 | event,
|
786 | request
|
787 | }) {
|
788 | if (typeof request === 'string') {
|
789 | request = new Request(request);
|
790 | }
|
791 |
|
792 | {
|
793 | assert_mjs.assert.isInstance(request, Request, {
|
794 | moduleName: 'workbox-strategies',
|
795 | className: 'NetworkOnly',
|
796 | funcName: 'handle',
|
797 | paramName: 'request'
|
798 | });
|
799 | }
|
800 |
|
801 | let error;
|
802 | let response;
|
803 |
|
804 | try {
|
805 | response = await fetchWrapper_mjs.fetchWrapper.fetch({
|
806 | request,
|
807 | event,
|
808 | fetchOptions: this._fetchOptions,
|
809 | plugins: this._plugins
|
810 | });
|
811 | } catch (err) {
|
812 | error = err;
|
813 | }
|
814 |
|
815 | {
|
816 | logger_mjs.logger.groupCollapsed(messages.strategyStart('NetworkOnly', request));
|
817 |
|
818 | if (response) {
|
819 | logger_mjs.logger.log(`Got response from network.`);
|
820 | } else {
|
821 | logger_mjs.logger.log(`Unable to get a response from the network.`);
|
822 | }
|
823 |
|
824 | messages.printFinalResponse(response);
|
825 | logger_mjs.logger.groupEnd();
|
826 | }
|
827 |
|
828 | if (!response) {
|
829 | throw new WorkboxError_mjs.WorkboxError('no-response', {
|
830 | url: request.url,
|
831 | error
|
832 | });
|
833 | }
|
834 |
|
835 | return response;
|
836 | }
|
837 |
|
838 | }
|
839 |
|
840 | /*
|
841 | Copyright 2018 Google LLC
|
842 |
|
843 | Use of this source code is governed by an MIT-style
|
844 | license that can be found in the LICENSE file or at
|
845 | https://opensource.org/licenses/MIT.
|
846 | */
|
847 | /**
|
848 | * An implementation of a
|
849 | * [stale-while-revalidate]{@link https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#stale-while-revalidate}
|
850 | * request strategy.
|
851 | *
|
852 | * Resources are requested from both the cache and the network in parallel.
|
853 | * The strategy will respond with the cached version if available, otherwise
|
854 | * wait for the network response. The cache is updated with the network response
|
855 | * with each successful request.
|
856 | *
|
857 | * By default, this strategy will cache responses with a 200 status code as
|
858 | * well as [opaque responses]{@link https://developers.google.com/web/tools/workbox/guides/handle-third-party-requests}.
|
859 | * Opaque responses are are cross-origin requests where the response doesn't
|
860 | * support [CORS]{@link https://enable-cors.org/}.
|
861 | *
|
862 | * If the network request fails, and there is no cache match, this will throw
|
863 | * a `WorkboxError` exception.
|
864 | *
|
865 | * @memberof workbox.strategies
|
866 | */
|
867 |
|
868 | class StaleWhileRevalidate {
|
869 | /**
|
870 | * @param {Object} options
|
871 | * @param {string} options.cacheName Cache name to store and retrieve
|
872 | * requests. Defaults to cache names provided by
|
873 | * [workbox-core]{@link workbox.core.cacheNames}.
|
874 | * @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}
|
875 | * to use in conjunction with this caching strategy.
|
876 | * @param {Object} options.fetchOptions Values passed along to the
|
877 | * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
|
878 | * of all fetch() requests made by this strategy.
|
879 | * @param {Object} options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions)
|
880 | */
|
881 | constructor(options = {}) {
|
882 | this._cacheName = cacheNames_mjs.cacheNames.getRuntimeName(options.cacheName);
|
883 | this._plugins = options.plugins || [];
|
884 |
|
885 | if (options.plugins) {
|
886 | let isUsingCacheWillUpdate = options.plugins.some(plugin => !!plugin.cacheWillUpdate);
|
887 | this._plugins = isUsingCacheWillUpdate ? options.plugins : [cacheOkAndOpaquePlugin, ...options.plugins];
|
888 | } else {
|
889 | // No plugins passed in, use the default plugin.
|
890 | this._plugins = [cacheOkAndOpaquePlugin];
|
891 | }
|
892 |
|
893 | this._fetchOptions = options.fetchOptions || null;
|
894 | this._matchOptions = options.matchOptions || null;
|
895 | }
|
896 | /**
|
897 | * This method will perform a request strategy and follows an API that
|
898 | * will work with the
|
899 | * [Workbox Router]{@link workbox.routing.Router}.
|
900 | *
|
901 | * @param {Object} options
|
902 | * @param {Request} options.request The request to run this strategy for.
|
903 | * @param {Event} [options.event] The event that triggered the request.
|
904 | * @return {Promise<Response>}
|
905 | */
|
906 |
|
907 |
|
908 | async handle({
|
909 | event,
|
910 | request
|
911 | }) {
|
912 | return this.makeRequest({
|
913 | event,
|
914 | request: request || event.request
|
915 | });
|
916 | }
|
917 | /**
|
918 | * This method can be used to perform a make a standalone request outside the
|
919 | * context of the [Workbox Router]{@link workbox.routing.Router}.
|
920 | *
|
921 | * See "[Advanced Recipes](https://developers.google.com/web/tools/workbox/guides/advanced-recipes#make-requests)"
|
922 | * for more usage information.
|
923 | *
|
924 | * @param {Object} options
|
925 | * @param {Request|string} options.request Either a
|
926 | * [`Request`]{@link https://developer.mozilla.org/en-US/docs/Web/API/Request}
|
927 | * object, or a string URL, corresponding to the request to be made.
|
928 | * @param {FetchEvent} [options.event] If provided, `event.waitUntil()` will
|
929 | * be called automatically to extend the service worker's lifetime.
|
930 | * @return {Promise<Response>}
|
931 | */
|
932 |
|
933 |
|
934 | async makeRequest({
|
935 | event,
|
936 | request
|
937 | }) {
|
938 | const logs = [];
|
939 |
|
940 | if (typeof request === 'string') {
|
941 | request = new Request(request);
|
942 | }
|
943 |
|
944 | {
|
945 | assert_mjs.assert.isInstance(request, Request, {
|
946 | moduleName: 'workbox-strategies',
|
947 | className: 'StaleWhileRevalidate',
|
948 | funcName: 'handle',
|
949 | paramName: 'request'
|
950 | });
|
951 | }
|
952 |
|
953 | const fetchAndCachePromise = this._getFromNetwork({
|
954 | request,
|
955 | event
|
956 | });
|
957 |
|
958 | let response = await cacheWrapper_mjs.cacheWrapper.match({
|
959 | cacheName: this._cacheName,
|
960 | request,
|
961 | event,
|
962 | matchOptions: this._matchOptions,
|
963 | plugins: this._plugins
|
964 | });
|
965 | let error;
|
966 |
|
967 | if (response) {
|
968 | {
|
969 | logs.push(`Found a cached response in the '${this._cacheName}'` + ` cache. Will update with the network response in the background.`);
|
970 | }
|
971 |
|
972 | if (event) {
|
973 | try {
|
974 | event.waitUntil(fetchAndCachePromise);
|
975 | } catch (error) {
|
976 | {
|
977 | logger_mjs.logger.warn(`Unable to ensure service worker stays alive when ` + `updating cache for '${getFriendlyURL_mjs.getFriendlyURL(request.url)}'.`);
|
978 | }
|
979 | }
|
980 | }
|
981 | } else {
|
982 | {
|
983 | logs.push(`No response found in the '${this._cacheName}' cache. ` + `Will wait for the network response.`);
|
984 | }
|
985 |
|
986 | try {
|
987 | response = await fetchAndCachePromise;
|
988 | } catch (err) {
|
989 | error = err;
|
990 | }
|
991 | }
|
992 |
|
993 | {
|
994 | logger_mjs.logger.groupCollapsed(messages.strategyStart('StaleWhileRevalidate', request));
|
995 |
|
996 | for (let log of logs) {
|
997 | logger_mjs.logger.log(log);
|
998 | }
|
999 |
|
1000 | messages.printFinalResponse(response);
|
1001 | logger_mjs.logger.groupEnd();
|
1002 | }
|
1003 |
|
1004 | if (!response) {
|
1005 | throw new WorkboxError_mjs.WorkboxError('no-response', {
|
1006 | url: request.url,
|
1007 | error
|
1008 | });
|
1009 | }
|
1010 |
|
1011 | return response;
|
1012 | }
|
1013 | /**
|
1014 | * @param {Object} options
|
1015 | * @param {Request} options.request
|
1016 | * @param {Event} [options.event]
|
1017 | * @return {Promise<Response>}
|
1018 | *
|
1019 | * @private
|
1020 | */
|
1021 |
|
1022 |
|
1023 | async _getFromNetwork({
|
1024 | request,
|
1025 | event
|
1026 | }) {
|
1027 | const response = await fetchWrapper_mjs.fetchWrapper.fetch({
|
1028 | request,
|
1029 | event,
|
1030 | fetchOptions: this._fetchOptions,
|
1031 | plugins: this._plugins
|
1032 | });
|
1033 | const cachePutPromise = cacheWrapper_mjs.cacheWrapper.put({
|
1034 | cacheName: this._cacheName,
|
1035 | request,
|
1036 | response: response.clone(),
|
1037 | event,
|
1038 | plugins: this._plugins
|
1039 | });
|
1040 |
|
1041 | if (event) {
|
1042 | try {
|
1043 | event.waitUntil(cachePutPromise);
|
1044 | } catch (error) {
|
1045 | {
|
1046 | logger_mjs.logger.warn(`Unable to ensure service worker stays alive when ` + `updating cache for '${getFriendlyURL_mjs.getFriendlyURL(request.url)}'.`);
|
1047 | }
|
1048 | }
|
1049 | }
|
1050 |
|
1051 | return response;
|
1052 | }
|
1053 |
|
1054 | }
|
1055 |
|
1056 | /*
|
1057 | Copyright 2018 Google LLC
|
1058 |
|
1059 | Use of this source code is governed by an MIT-style
|
1060 | license that can be found in the LICENSE file or at
|
1061 | https://opensource.org/licenses/MIT.
|
1062 | */
|
1063 | const mapping = {
|
1064 | cacheFirst: CacheFirst,
|
1065 | cacheOnly: CacheOnly,
|
1066 | networkFirst: NetworkFirst,
|
1067 | networkOnly: NetworkOnly,
|
1068 | staleWhileRevalidate: StaleWhileRevalidate
|
1069 | };
|
1070 |
|
1071 | const deprecate = strategy => {
|
1072 | const StrategyCtr = mapping[strategy];
|
1073 | return options => {
|
1074 | {
|
1075 | const strategyCtrName = strategy[0].toUpperCase() + strategy.slice(1);
|
1076 | logger_mjs.logger.warn(`The 'workbox.strategies.${strategy}()' function has been ` + `deprecated and will be removed in a future version of Workbox.\n` + `Please use 'new workbox.strategies.${strategyCtrName}()' instead.`);
|
1077 | }
|
1078 |
|
1079 | return new StrategyCtr(options);
|
1080 | };
|
1081 | };
|
1082 | /**
|
1083 | * @function workbox.strategies.cacheFirst
|
1084 | * @param {Object} options See the {@link workbox.strategies.CacheFirst}
|
1085 | * constructor for more info.
|
1086 | * @deprecated since v4.0.0
|
1087 | */
|
1088 |
|
1089 |
|
1090 | const cacheFirst = deprecate('cacheFirst');
|
1091 | /**
|
1092 | * @function workbox.strategies.cacheOnly
|
1093 | * @param {Object} options See the {@link workbox.strategies.CacheOnly}
|
1094 | * constructor for more info.
|
1095 | * @deprecated since v4.0.0
|
1096 | */
|
1097 |
|
1098 | const cacheOnly = deprecate('cacheOnly');
|
1099 | /**
|
1100 | * @function workbox.strategies.networkFirst
|
1101 | * @param {Object} options See the {@link workbox.strategies.NetworkFirst}
|
1102 | * constructor for more info.
|
1103 | * @deprecated since v4.0.0
|
1104 | */
|
1105 |
|
1106 | const networkFirst = deprecate('networkFirst');
|
1107 | /**
|
1108 | * @function workbox.strategies.networkOnly
|
1109 | * @param {Object} options See the {@link workbox.strategies.NetworkOnly}
|
1110 | * constructor for more info.
|
1111 | * @deprecated since v4.0.0
|
1112 | */
|
1113 |
|
1114 | const networkOnly = deprecate('networkOnly');
|
1115 | /**
|
1116 | * @function workbox.strategies.staleWhileRevalidate
|
1117 | * @param {Object} options See the
|
1118 | * {@link workbox.strategies.StaleWhileRevalidate} constructor for more info.
|
1119 | * @deprecated since v4.0.0
|
1120 | */
|
1121 |
|
1122 | const staleWhileRevalidate = deprecate('staleWhileRevalidate');
|
1123 |
|
1124 | exports.CacheFirst = CacheFirst;
|
1125 | exports.CacheOnly = CacheOnly;
|
1126 | exports.NetworkFirst = NetworkFirst;
|
1127 | exports.NetworkOnly = NetworkOnly;
|
1128 | exports.StaleWhileRevalidate = StaleWhileRevalidate;
|
1129 | exports.cacheFirst = cacheFirst;
|
1130 | exports.cacheOnly = cacheOnly;
|
1131 | exports.networkFirst = networkFirst;
|
1132 | exports.networkOnly = networkOnly;
|
1133 | exports.staleWhileRevalidate = staleWhileRevalidate;
|
1134 |
|
1135 | return exports;
|
1136 |
|
1137 | }({}, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private));
|
1138 |
|