source: frontend/node_modules/workbox-precaching/PrecacheStrategy.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 10.5 KB
Line 
1/*
2 Copyright 2020 Google LLC
3
4 Use of this source code is governed by an MIT-style
5 license that can be found in the LICENSE file or at
6 https://opensource.org/licenses/MIT.
7*/
8import { copyResponse } from 'workbox-core/copyResponse.js';
9import { cacheNames } from 'workbox-core/_private/cacheNames.js';
10import { getFriendlyURL } from 'workbox-core/_private/getFriendlyURL.js';
11import { logger } from 'workbox-core/_private/logger.js';
12import { WorkboxError } from 'workbox-core/_private/WorkboxError.js';
13import { Strategy } from 'workbox-strategies/Strategy.js';
14import './_version.js';
15/**
16 * A {@link workbox-strategies.Strategy} implementation
17 * specifically designed to work with
18 * {@link workbox-precaching.PrecacheController}
19 * to both cache and fetch precached assets.
20 *
21 * Note: an instance of this class is created automatically when creating a
22 * `PrecacheController`; it's generally not necessary to create this yourself.
23 *
24 * @extends workbox-strategies.Strategy
25 * @memberof workbox-precaching
26 */
27class PrecacheStrategy extends Strategy {
28 /**
29 *
30 * @param {Object} [options]
31 * @param {string} [options.cacheName] Cache name to store and retrieve
32 * requests. Defaults to the cache names provided by
33 * {@link workbox-core.cacheNames}.
34 * @param {Array<Object>} [options.plugins] {@link https://developers.google.com/web/tools/workbox/guides/using-plugins|Plugins}
35 * to use in conjunction with this caching strategy.
36 * @param {Object} [options.fetchOptions] Values passed along to the
37 * {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters|init}
38 * of all fetch() requests made by this strategy.
39 * @param {Object} [options.matchOptions] The
40 * {@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions|CacheQueryOptions}
41 * for any `cache.match()` or `cache.put()` calls made by this strategy.
42 * @param {boolean} [options.fallbackToNetwork=true] Whether to attempt to
43 * get the response from the network if there's a precache miss.
44 */
45 constructor(options = {}) {
46 options.cacheName = cacheNames.getPrecacheName(options.cacheName);
47 super(options);
48 this._fallbackToNetwork =
49 options.fallbackToNetwork === false ? false : true;
50 // Redirected responses cannot be used to satisfy a navigation request, so
51 // any redirected response must be "copied" rather than cloned, so the new
52 // response doesn't contain the `redirected` flag. See:
53 // https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1
54 this.plugins.push(PrecacheStrategy.copyRedirectedCacheableResponsesPlugin);
55 }
56 /**
57 * @private
58 * @param {Request|string} request A request to run this strategy for.
59 * @param {workbox-strategies.StrategyHandler} handler The event that
60 * triggered the request.
61 * @return {Promise<Response>}
62 */
63 async _handle(request, handler) {
64 const response = await handler.cacheMatch(request);
65 if (response) {
66 return response;
67 }
68 // If this is an `install` event for an entry that isn't already cached,
69 // then populate the cache.
70 if (handler.event && handler.event.type === 'install') {
71 return await this._handleInstall(request, handler);
72 }
73 // Getting here means something went wrong. An entry that should have been
74 // precached wasn't found in the cache.
75 return await this._handleFetch(request, handler);
76 }
77 async _handleFetch(request, handler) {
78 let response;
79 const params = (handler.params || {});
80 // Fall back to the network if we're configured to do so.
81 if (this._fallbackToNetwork) {
82 if (process.env.NODE_ENV !== 'production') {
83 logger.warn(`The precached response for ` +
84 `${getFriendlyURL(request.url)} in ${this.cacheName} was not ` +
85 `found. Falling back to the network.`);
86 }
87 const integrityInManifest = params.integrity;
88 const integrityInRequest = request.integrity;
89 const noIntegrityConflict = !integrityInRequest || integrityInRequest === integrityInManifest;
90 // Do not add integrity if the original request is no-cors
91 // See https://github.com/GoogleChrome/workbox/issues/3096
92 response = await handler.fetch(new Request(request, {
93 integrity: request.mode !== 'no-cors'
94 ? integrityInRequest || integrityInManifest
95 : undefined,
96 }));
97 // It's only "safe" to repair the cache if we're using SRI to guarantee
98 // that the response matches the precache manifest's expectations,
99 // and there's either a) no integrity property in the incoming request
100 // or b) there is an integrity, and it matches the precache manifest.
101 // See https://github.com/GoogleChrome/workbox/issues/2858
102 // Also if the original request users no-cors we don't use integrity.
103 // See https://github.com/GoogleChrome/workbox/issues/3096
104 if (integrityInManifest &&
105 noIntegrityConflict &&
106 request.mode !== 'no-cors') {
107 this._useDefaultCacheabilityPluginIfNeeded();
108 const wasCached = await handler.cachePut(request, response.clone());
109 if (process.env.NODE_ENV !== 'production') {
110 if (wasCached) {
111 logger.log(`A response for ${getFriendlyURL(request.url)} ` +
112 `was used to "repair" the precache.`);
113 }
114 }
115 }
116 }
117 else {
118 // This shouldn't normally happen, but there are edge cases:
119 // https://github.com/GoogleChrome/workbox/issues/1441
120 throw new WorkboxError('missing-precache-entry', {
121 cacheName: this.cacheName,
122 url: request.url,
123 });
124 }
125 if (process.env.NODE_ENV !== 'production') {
126 const cacheKey = params.cacheKey || (await handler.getCacheKey(request, 'read'));
127 // Workbox is going to handle the route.
128 // print the routing details to the console.
129 logger.groupCollapsed(`Precaching is responding to: ` + getFriendlyURL(request.url));
130 logger.log(`Serving the precached url: ${getFriendlyURL(cacheKey instanceof Request ? cacheKey.url : cacheKey)}`);
131 logger.groupCollapsed(`View request details here.`);
132 logger.log(request);
133 logger.groupEnd();
134 logger.groupCollapsed(`View response details here.`);
135 logger.log(response);
136 logger.groupEnd();
137 logger.groupEnd();
138 }
139 return response;
140 }
141 async _handleInstall(request, handler) {
142 this._useDefaultCacheabilityPluginIfNeeded();
143 const response = await handler.fetch(request);
144 // Make sure we defer cachePut() until after we know the response
145 // should be cached; see https://github.com/GoogleChrome/workbox/issues/2737
146 const wasCached = await handler.cachePut(request, response.clone());
147 if (!wasCached) {
148 // Throwing here will lead to the `install` handler failing, which
149 // we want to do if *any* of the responses aren't safe to cache.
150 throw new WorkboxError('bad-precaching-response', {
151 url: request.url,
152 status: response.status,
153 });
154 }
155 return response;
156 }
157 /**
158 * This method is complex, as there a number of things to account for:
159 *
160 * The `plugins` array can be set at construction, and/or it might be added to
161 * to at any time before the strategy is used.
162 *
163 * At the time the strategy is used (i.e. during an `install` event), there
164 * needs to be at least one plugin that implements `cacheWillUpdate` in the
165 * array, other than `copyRedirectedCacheableResponsesPlugin`.
166 *
167 * - If this method is called and there are no suitable `cacheWillUpdate`
168 * plugins, we need to add `defaultPrecacheCacheabilityPlugin`.
169 *
170 * - If this method is called and there is exactly one `cacheWillUpdate`, then
171 * we don't have to do anything (this might be a previously added
172 * `defaultPrecacheCacheabilityPlugin`, or it might be a custom plugin).
173 *
174 * - If this method is called and there is more than one `cacheWillUpdate`,
175 * then we need to check if one is `defaultPrecacheCacheabilityPlugin`. If so,
176 * we need to remove it. (This situation is unlikely, but it could happen if
177 * the strategy is used multiple times, the first without a `cacheWillUpdate`,
178 * and then later on after manually adding a custom `cacheWillUpdate`.)
179 *
180 * See https://github.com/GoogleChrome/workbox/issues/2737 for more context.
181 *
182 * @private
183 */
184 _useDefaultCacheabilityPluginIfNeeded() {
185 let defaultPluginIndex = null;
186 let cacheWillUpdatePluginCount = 0;
187 for (const [index, plugin] of this.plugins.entries()) {
188 // Ignore the copy redirected plugin when determining what to do.
189 if (plugin === PrecacheStrategy.copyRedirectedCacheableResponsesPlugin) {
190 continue;
191 }
192 // Save the default plugin's index, in case it needs to be removed.
193 if (plugin === PrecacheStrategy.defaultPrecacheCacheabilityPlugin) {
194 defaultPluginIndex = index;
195 }
196 if (plugin.cacheWillUpdate) {
197 cacheWillUpdatePluginCount++;
198 }
199 }
200 if (cacheWillUpdatePluginCount === 0) {
201 this.plugins.push(PrecacheStrategy.defaultPrecacheCacheabilityPlugin);
202 }
203 else if (cacheWillUpdatePluginCount > 1 && defaultPluginIndex !== null) {
204 // Only remove the default plugin; multiple custom plugins are allowed.
205 this.plugins.splice(defaultPluginIndex, 1);
206 }
207 // Nothing needs to be done if cacheWillUpdatePluginCount is 1
208 }
209}
210PrecacheStrategy.defaultPrecacheCacheabilityPlugin = {
211 async cacheWillUpdate({ response }) {
212 if (!response || response.status >= 400) {
213 return null;
214 }
215 return response;
216 },
217};
218PrecacheStrategy.copyRedirectedCacheableResponsesPlugin = {
219 async cacheWillUpdate({ response }) {
220 return response.redirected ? await copyResponse(response) : response;
221 },
222};
223export { PrecacheStrategy };
Note: See TracBrowser for help on using the repository browser.