workbox-strategies.dev.js 35 KB

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