UNPKG

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