@serwist/precaching 8.4.4 → 9.0.0-preview.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PrecacheController.d.ts +4 -3
- package/dist/PrecacheController.d.ts.map +1 -0
- package/dist/PrecacheFallbackPlugin.d.ts +1 -0
- package/dist/PrecacheFallbackPlugin.d.ts.map +1 -0
- package/dist/PrecacheRoute.d.ts +1 -0
- package/dist/PrecacheRoute.d.ts.map +1 -0
- package/dist/PrecacheStrategy.d.ts +1 -0
- package/dist/PrecacheStrategy.d.ts.map +1 -0
- package/dist/_types.d.ts +3 -2
- package/dist/_types.d.ts.map +1 -0
- package/dist/addPlugins.d.ts +1 -0
- package/dist/addPlugins.d.ts.map +1 -0
- package/dist/addRoute.d.ts +1 -0
- package/dist/addRoute.d.ts.map +1 -0
- package/dist/cleanupOutdatedCaches.d.ts +1 -0
- package/dist/cleanupOutdatedCaches.d.ts.map +1 -0
- package/dist/createHandlerBoundToURL.d.ts +1 -0
- package/dist/createHandlerBoundToURL.d.ts.map +1 -0
- package/dist/getCacheKeyForURL.d.ts +1 -0
- package/dist/getCacheKeyForURL.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -427
- package/dist/matchPrecache.d.ts +1 -0
- package/dist/matchPrecache.d.ts.map +1 -0
- package/dist/precache.d.ts +2 -1
- package/dist/precache.d.ts.map +1 -0
- package/dist/precacheAndRoute.d.ts +2 -1
- package/dist/precacheAndRoute.d.ts.map +1 -0
- package/dist/utils/PrecacheCacheKeyPlugin.d.ts +1 -0
- package/dist/utils/PrecacheCacheKeyPlugin.d.ts.map +1 -0
- package/dist/utils/PrecacheInstallReportPlugin.d.ts +1 -0
- package/dist/utils/PrecacheInstallReportPlugin.d.ts.map +1 -0
- package/dist/utils/createCacheKey.d.ts +1 -0
- package/dist/utils/createCacheKey.d.ts.map +1 -0
- package/dist/utils/deleteOutdatedCaches.d.ts +1 -0
- package/dist/utils/deleteOutdatedCaches.d.ts.map +1 -0
- package/dist/utils/generateURLVariations.d.ts +1 -0
- package/dist/utils/generateURLVariations.d.ts.map +1 -0
- package/dist/utils/getCacheKeyForURL.d.ts +1 -0
- package/dist/utils/getCacheKeyForURL.d.ts.map +1 -0
- package/dist/utils/getOrCreatePrecacheController.d.ts +1 -0
- package/dist/utils/getOrCreatePrecacheController.d.ts.map +1 -0
- package/dist/utils/printCleanupDetails.d.ts +1 -0
- package/dist/utils/printCleanupDetails.d.ts.map +1 -0
- package/dist/utils/printInstallDetails.d.ts +1 -0
- package/dist/utils/printInstallDetails.d.ts.map +1 -0
- package/dist/utils/removeIgnoredSearchParams.d.ts +1 -0
- package/dist/utils/removeIgnoredSearchParams.d.ts.map +1 -0
- package/package.json +20 -18
- package/src/PrecacheController.ts +331 -0
- package/src/PrecacheFallbackPlugin.ts +61 -0
- package/src/PrecacheRoute.ts +50 -0
- package/src/PrecacheStrategy.ts +239 -0
- package/src/_types.ts +46 -0
- package/src/addPlugins.ts +23 -0
- package/src/addRoute.ts +33 -0
- package/src/cleanupOutdatedCaches.ts +34 -0
- package/src/createHandlerBoundToURL.ts +32 -0
- package/src/getCacheKeyForURL.ts +33 -0
- package/{dist/index.d.cts → src/index.ts} +25 -1
- package/src/matchPrecache.ts +28 -0
- package/src/precache.ts +33 -0
- package/src/precacheAndRoute.ts +29 -0
- package/src/utils/PrecacheCacheKeyPlugin.ts +36 -0
- package/src/utils/PrecacheInstallReportPlugin.ts +49 -0
- package/src/utils/createCacheKey.ts +68 -0
- package/src/utils/deleteOutdatedCaches.ts +42 -0
- package/src/utils/generateURLVariations.ts +55 -0
- package/src/utils/getCacheKeyForURL.ts +36 -0
- package/src/utils/getOrCreatePrecacheController.ts +22 -0
- package/src/utils/printCleanupDetails.ts +38 -0
- package/src/utils/printInstallDetails.ts +53 -0
- package/src/utils/removeIgnoredSearchParams.ts +29 -0
- package/dist/index.cjs +0 -930
package/dist/index.cjs
DELETED
|
@@ -1,930 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var internal = require('@serwist/core/internal');
|
|
4
|
-
var core = require('@serwist/core');
|
|
5
|
-
var strategies = require('@serwist/strategies');
|
|
6
|
-
var routing = require('@serwist/routing');
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* A `@serwist/strategies.Strategy` implementation
|
|
10
|
-
* specifically designed to work with
|
|
11
|
-
* `@serwist/precaching.PrecacheController`
|
|
12
|
-
* to both cache and fetch precached assets.
|
|
13
|
-
*
|
|
14
|
-
* Note: an instance of this class is created automatically when creating a
|
|
15
|
-
* `PrecacheController`; it's generally not necessary to create this yourself.
|
|
16
|
-
*/ class PrecacheStrategy extends strategies.Strategy {
|
|
17
|
-
_fallbackToNetwork;
|
|
18
|
-
static defaultPrecacheCacheabilityPlugin = {
|
|
19
|
-
async cacheWillUpdate ({ response }) {
|
|
20
|
-
if (!response || response.status >= 400) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
return response;
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
static copyRedirectedCacheableResponsesPlugin = {
|
|
27
|
-
async cacheWillUpdate ({ response }) {
|
|
28
|
-
return response.redirected ? await core.copyResponse(response) : response;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
/**
|
|
32
|
-
* @param options
|
|
33
|
-
*/ constructor(options = {}){
|
|
34
|
-
options.cacheName = internal.privateCacheNames.getPrecacheName(options.cacheName);
|
|
35
|
-
super(options);
|
|
36
|
-
this._fallbackToNetwork = options.fallbackToNetwork === false ? false : true;
|
|
37
|
-
// Redirected responses cannot be used to satisfy a navigation request, so
|
|
38
|
-
// any redirected response must be "copied" rather than cloned, so the new
|
|
39
|
-
// response doesn't contain the `redirected` flag. See:
|
|
40
|
-
// https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1
|
|
41
|
-
this.plugins.push(PrecacheStrategy.copyRedirectedCacheableResponsesPlugin);
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* @private
|
|
45
|
-
* @param request A request to run this strategy for.
|
|
46
|
-
* @param handler The event that triggered the request.
|
|
47
|
-
* @returns
|
|
48
|
-
*/ async _handle(request, handler) {
|
|
49
|
-
const response = await handler.cacheMatch(request);
|
|
50
|
-
if (response) {
|
|
51
|
-
return response;
|
|
52
|
-
}
|
|
53
|
-
// If this is an `install` event for an entry that isn't already cached,
|
|
54
|
-
// then populate the cache.
|
|
55
|
-
if (handler.event && handler.event.type === "install") {
|
|
56
|
-
return await this._handleInstall(request, handler);
|
|
57
|
-
}
|
|
58
|
-
// Getting here means something went wrong. An entry that should have been
|
|
59
|
-
// precached wasn't found in the cache.
|
|
60
|
-
return await this._handleFetch(request, handler);
|
|
61
|
-
}
|
|
62
|
-
async _handleFetch(request, handler) {
|
|
63
|
-
let response = undefined;
|
|
64
|
-
const params = handler.params || {};
|
|
65
|
-
// Fallback to the network if we're configured to do so.
|
|
66
|
-
if (this._fallbackToNetwork) {
|
|
67
|
-
if (process.env.NODE_ENV !== "production") {
|
|
68
|
-
internal.logger.warn(`The precached response for ${internal.getFriendlyURL(request.url)} in ${this.cacheName} was not found. Falling back to the network.`);
|
|
69
|
-
}
|
|
70
|
-
const integrityInManifest = params.integrity;
|
|
71
|
-
const integrityInRequest = request.integrity;
|
|
72
|
-
const noIntegrityConflict = !integrityInRequest || integrityInRequest === integrityInManifest;
|
|
73
|
-
// Do not add integrity if the original request is no-cors
|
|
74
|
-
// See https://github.com/GoogleChrome/workbox/issues/3096
|
|
75
|
-
response = await handler.fetch(new Request(request, {
|
|
76
|
-
integrity: request.mode !== "no-cors" ? integrityInRequest || integrityInManifest : undefined
|
|
77
|
-
}));
|
|
78
|
-
// It's only "safe" to repair the cache if we're using SRI to guarantee
|
|
79
|
-
// that the response matches the precache manifest's expectations,
|
|
80
|
-
// and there's either a) no integrity property in the incoming request
|
|
81
|
-
// or b) there is an integrity, and it matches the precache manifest.
|
|
82
|
-
// See https://github.com/GoogleChrome/workbox/issues/2858
|
|
83
|
-
// Also if the original request users no-cors we don't use integrity.
|
|
84
|
-
// See https://github.com/GoogleChrome/workbox/issues/3096
|
|
85
|
-
if (integrityInManifest && noIntegrityConflict && request.mode !== "no-cors") {
|
|
86
|
-
this._useDefaultCacheabilityPluginIfNeeded();
|
|
87
|
-
const wasCached = await handler.cachePut(request, response.clone());
|
|
88
|
-
if (process.env.NODE_ENV !== "production") {
|
|
89
|
-
if (wasCached) {
|
|
90
|
-
internal.logger.log(`A response for ${internal.getFriendlyURL(request.url)} was used to "repair" the precache.`);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
} else {
|
|
95
|
-
// This shouldn't normally happen, but there are edge cases:
|
|
96
|
-
// https://github.com/GoogleChrome/workbox/issues/1441
|
|
97
|
-
throw new internal.SerwistError("missing-precache-entry", {
|
|
98
|
-
cacheName: this.cacheName,
|
|
99
|
-
url: request.url
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
if (process.env.NODE_ENV !== "production") {
|
|
103
|
-
const cacheKey = params.cacheKey || await handler.getCacheKey(request, "read");
|
|
104
|
-
// Serwist is going to handle the route.
|
|
105
|
-
// print the routing details to the console.
|
|
106
|
-
internal.logger.groupCollapsed(`Precaching is responding to: ${internal.getFriendlyURL(request.url)}`);
|
|
107
|
-
internal.logger.log(`Serving the precached url: ${internal.getFriendlyURL(cacheKey instanceof Request ? cacheKey.url : cacheKey)}`);
|
|
108
|
-
internal.logger.groupCollapsed("View request details here.");
|
|
109
|
-
internal.logger.log(request);
|
|
110
|
-
internal.logger.groupEnd();
|
|
111
|
-
internal.logger.groupCollapsed("View response details here.");
|
|
112
|
-
internal.logger.log(response);
|
|
113
|
-
internal.logger.groupEnd();
|
|
114
|
-
internal.logger.groupEnd();
|
|
115
|
-
}
|
|
116
|
-
return response;
|
|
117
|
-
}
|
|
118
|
-
async _handleInstall(request, handler) {
|
|
119
|
-
this._useDefaultCacheabilityPluginIfNeeded();
|
|
120
|
-
const response = await handler.fetch(request);
|
|
121
|
-
// Make sure we defer cachePut() until after we know the response
|
|
122
|
-
// should be cached; see https://github.com/GoogleChrome/workbox/issues/2737
|
|
123
|
-
const wasCached = await handler.cachePut(request, response.clone());
|
|
124
|
-
if (!wasCached) {
|
|
125
|
-
// Throwing here will lead to the `install` handler failing, which
|
|
126
|
-
// we want to do if *any* of the responses aren't safe to cache.
|
|
127
|
-
throw new internal.SerwistError("bad-precaching-response", {
|
|
128
|
-
url: request.url,
|
|
129
|
-
status: response.status
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
return response;
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* This method is complex, as there a number of things to account for:
|
|
136
|
-
*
|
|
137
|
-
* The `plugins` array can be set at construction, and/or it might be added to
|
|
138
|
-
* to at any time before the strategy is used.
|
|
139
|
-
*
|
|
140
|
-
* At the time the strategy is used (i.e. during an `install` event), there
|
|
141
|
-
* needs to be at least one plugin that implements `cacheWillUpdate` in the
|
|
142
|
-
* array, other than `copyRedirectedCacheableResponsesPlugin`.
|
|
143
|
-
*
|
|
144
|
-
* - If this method is called and there are no suitable `cacheWillUpdate`
|
|
145
|
-
* plugins, we need to add `defaultPrecacheCacheabilityPlugin`.
|
|
146
|
-
*
|
|
147
|
-
* - If this method is called and there is exactly one `cacheWillUpdate`, then
|
|
148
|
-
* we don't have to do anything (this might be a previously added
|
|
149
|
-
* `defaultPrecacheCacheabilityPlugin`, or it might be a custom plugin).
|
|
150
|
-
*
|
|
151
|
-
* - If this method is called and there is more than one `cacheWillUpdate`,
|
|
152
|
-
* then we need to check if one is `defaultPrecacheCacheabilityPlugin`. If so,
|
|
153
|
-
* we need to remove it. (This situation is unlikely, but it could happen if
|
|
154
|
-
* the strategy is used multiple times, the first without a `cacheWillUpdate`,
|
|
155
|
-
* and then later on after manually adding a custom `cacheWillUpdate`.)
|
|
156
|
-
*
|
|
157
|
-
* See https://github.com/GoogleChrome/workbox/issues/2737 for more context.
|
|
158
|
-
*
|
|
159
|
-
* @private
|
|
160
|
-
*/ _useDefaultCacheabilityPluginIfNeeded() {
|
|
161
|
-
let defaultPluginIndex = null;
|
|
162
|
-
let cacheWillUpdatePluginCount = 0;
|
|
163
|
-
for (const [index, plugin] of this.plugins.entries()){
|
|
164
|
-
// Ignore the copy redirected plugin when determining what to do.
|
|
165
|
-
if (plugin === PrecacheStrategy.copyRedirectedCacheableResponsesPlugin) {
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
// Save the default plugin's index, in case it needs to be removed.
|
|
169
|
-
if (plugin === PrecacheStrategy.defaultPrecacheCacheabilityPlugin) {
|
|
170
|
-
defaultPluginIndex = index;
|
|
171
|
-
}
|
|
172
|
-
if (plugin.cacheWillUpdate) {
|
|
173
|
-
cacheWillUpdatePluginCount++;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
if (cacheWillUpdatePluginCount === 0) {
|
|
177
|
-
this.plugins.push(PrecacheStrategy.defaultPrecacheCacheabilityPlugin);
|
|
178
|
-
} else if (cacheWillUpdatePluginCount > 1 && defaultPluginIndex !== null) {
|
|
179
|
-
// Only remove the default plugin; multiple custom plugins are allowed.
|
|
180
|
-
this.plugins.splice(defaultPluginIndex, 1);
|
|
181
|
-
}
|
|
182
|
-
// Nothing needs to be done if cacheWillUpdatePluginCount is 1
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/*
|
|
187
|
-
Copyright 2020 Google LLC
|
|
188
|
-
|
|
189
|
-
Use of this source code is governed by an MIT-style
|
|
190
|
-
license that can be found in the LICENSE file or at
|
|
191
|
-
https://opensource.org/licenses/MIT.
|
|
192
|
-
*/ /**
|
|
193
|
-
* A plugin, designed to be used with PrecacheController, to translate URLs into
|
|
194
|
-
* the corresponding cache key, based on the current revision info.
|
|
195
|
-
*
|
|
196
|
-
* @private
|
|
197
|
-
*/ class PrecacheCacheKeyPlugin {
|
|
198
|
-
_precacheController;
|
|
199
|
-
constructor({ precacheController }){
|
|
200
|
-
this._precacheController = precacheController;
|
|
201
|
-
}
|
|
202
|
-
cacheKeyWillBeUsed = async ({ request, params })=>{
|
|
203
|
-
// Params is type any, can't change right now.
|
|
204
|
-
/* eslint-disable */ const cacheKey = params?.cacheKey || this._precacheController.getCacheKeyForURL(request.url);
|
|
205
|
-
/* eslint-enable */ return cacheKey ? new Request(cacheKey, {
|
|
206
|
-
headers: request.headers
|
|
207
|
-
}) : request;
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/*
|
|
212
|
-
Copyright 2020 Google LLC
|
|
213
|
-
|
|
214
|
-
Use of this source code is governed by an MIT-style
|
|
215
|
-
license that can be found in the LICENSE file or at
|
|
216
|
-
https://opensource.org/licenses/MIT.
|
|
217
|
-
*/ /**
|
|
218
|
-
* A plugin, designed to be used with PrecacheController, to determine the
|
|
219
|
-
* of assets that were updated (or not updated) during the install event.
|
|
220
|
-
*
|
|
221
|
-
* @private
|
|
222
|
-
*/ class PrecacheInstallReportPlugin {
|
|
223
|
-
updatedURLs = [];
|
|
224
|
-
notUpdatedURLs = [];
|
|
225
|
-
handlerWillStart = async ({ request, state })=>{
|
|
226
|
-
// TODO: `state` should never be undefined...
|
|
227
|
-
if (state) {
|
|
228
|
-
state.originalRequest = request;
|
|
229
|
-
}
|
|
230
|
-
};
|
|
231
|
-
cachedResponseWillBeUsed = async ({ event, state, cachedResponse })=>{
|
|
232
|
-
if (event.type === "install") {
|
|
233
|
-
if (state?.originalRequest && state.originalRequest instanceof Request) {
|
|
234
|
-
// TODO: `state` should never be undefined...
|
|
235
|
-
const url = state.originalRequest.url;
|
|
236
|
-
if (cachedResponse) {
|
|
237
|
-
this.notUpdatedURLs.push(url);
|
|
238
|
-
} else {
|
|
239
|
-
this.updatedURLs.push(url);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
return cachedResponse;
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Name of the search parameter used to store revision info.
|
|
248
|
-
const REVISION_SEARCH_PARAM = "__WB_REVISION__";
|
|
249
|
-
/**
|
|
250
|
-
* Converts a manifest entry into a versioned URL suitable for precaching.
|
|
251
|
-
*
|
|
252
|
-
* @param entry
|
|
253
|
-
* @returns A URL with versioning info.
|
|
254
|
-
*
|
|
255
|
-
* @private
|
|
256
|
-
*/ function createCacheKey(entry) {
|
|
257
|
-
if (!entry) {
|
|
258
|
-
throw new internal.SerwistError("add-to-cache-list-unexpected-type", {
|
|
259
|
-
entry
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
// If a precache manifest entry is a string, it's assumed to be a versioned
|
|
263
|
-
// URL, like '/app.abcd1234.js'. Return as-is.
|
|
264
|
-
if (typeof entry === "string") {
|
|
265
|
-
const urlObject = new URL(entry, location.href);
|
|
266
|
-
return {
|
|
267
|
-
cacheKey: urlObject.href,
|
|
268
|
-
url: urlObject.href
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
const { revision, url } = entry;
|
|
272
|
-
if (!url) {
|
|
273
|
-
throw new internal.SerwistError("add-to-cache-list-unexpected-type", {
|
|
274
|
-
entry
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
// If there's just a URL and no revision, then it's also assumed to be a
|
|
278
|
-
// versioned URL.
|
|
279
|
-
if (!revision) {
|
|
280
|
-
const urlObject = new URL(url, location.href);
|
|
281
|
-
return {
|
|
282
|
-
cacheKey: urlObject.href,
|
|
283
|
-
url: urlObject.href
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
// Otherwise, construct a properly versioned URL using the custom Serwist
|
|
287
|
-
// search parameter along with the revision info.
|
|
288
|
-
const cacheKeyURL = new URL(url, location.href);
|
|
289
|
-
const originalURL = new URL(url, location.href);
|
|
290
|
-
cacheKeyURL.searchParams.set(REVISION_SEARCH_PARAM, revision);
|
|
291
|
-
return {
|
|
292
|
-
cacheKey: cacheKeyURL.href,
|
|
293
|
-
url: originalURL.href
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* @param groupTitle
|
|
299
|
-
* @param deletedURLs
|
|
300
|
-
*
|
|
301
|
-
* @private
|
|
302
|
-
*/ const logGroup = (groupTitle, deletedURLs)=>{
|
|
303
|
-
internal.logger.groupCollapsed(groupTitle);
|
|
304
|
-
for (const url of deletedURLs){
|
|
305
|
-
internal.logger.log(url);
|
|
306
|
-
}
|
|
307
|
-
internal.logger.groupEnd();
|
|
308
|
-
};
|
|
309
|
-
/**
|
|
310
|
-
* @param deletedURLs
|
|
311
|
-
* @private
|
|
312
|
-
*/ function printCleanupDetails(deletedURLs) {
|
|
313
|
-
const deletionCount = deletedURLs.length;
|
|
314
|
-
if (deletionCount > 0) {
|
|
315
|
-
internal.logger.groupCollapsed(`During precaching cleanup, ${deletionCount} cached request${deletionCount === 1 ? " was" : "s were"} deleted.`);
|
|
316
|
-
logGroup("Deleted Cache Requests", deletedURLs);
|
|
317
|
-
internal.logger.groupEnd();
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* @param groupTitle
|
|
323
|
-
* @param urls
|
|
324
|
-
*
|
|
325
|
-
* @private
|
|
326
|
-
*/ function _nestedGroup(groupTitle, urls) {
|
|
327
|
-
if (urls.length === 0) {
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
internal.logger.groupCollapsed(groupTitle);
|
|
331
|
-
for (const url of urls){
|
|
332
|
-
internal.logger.log(url);
|
|
333
|
-
}
|
|
334
|
-
internal.logger.groupEnd();
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* @param urlsToPrecache
|
|
338
|
-
* @param urlsAlreadyPrecached
|
|
339
|
-
* @private
|
|
340
|
-
*/ function printInstallDetails(urlsToPrecache, urlsAlreadyPrecached) {
|
|
341
|
-
const precachedCount = urlsToPrecache.length;
|
|
342
|
-
const alreadyPrecachedCount = urlsAlreadyPrecached.length;
|
|
343
|
-
if (precachedCount || alreadyPrecachedCount) {
|
|
344
|
-
let message = `Precaching ${precachedCount} file${precachedCount === 1 ? "" : "s"}.`;
|
|
345
|
-
if (alreadyPrecachedCount > 0) {
|
|
346
|
-
message += ` ${alreadyPrecachedCount} ` + `file${alreadyPrecachedCount === 1 ? " is" : "s are"} already cached.`;
|
|
347
|
-
}
|
|
348
|
-
internal.logger.groupCollapsed(message);
|
|
349
|
-
_nestedGroup("View newly precached URLs.", urlsToPrecache);
|
|
350
|
-
_nestedGroup("View previously precached URLs.", urlsAlreadyPrecached);
|
|
351
|
-
internal.logger.groupEnd();
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
/**
|
|
356
|
-
* Performs efficient precaching of assets.
|
|
357
|
-
*/ class PrecacheController {
|
|
358
|
-
_installAndActiveListenersAdded;
|
|
359
|
-
_strategy;
|
|
360
|
-
_urlsToCacheKeys = new Map();
|
|
361
|
-
_urlsToCacheModes = new Map();
|
|
362
|
-
_cacheKeysToIntegrities = new Map();
|
|
363
|
-
/**
|
|
364
|
-
* Create a new PrecacheController.
|
|
365
|
-
*
|
|
366
|
-
* @param options
|
|
367
|
-
*/ constructor({ cacheName, plugins = [], fallbackToNetwork = true } = {}){
|
|
368
|
-
this._strategy = new PrecacheStrategy({
|
|
369
|
-
cacheName: internal.privateCacheNames.getPrecacheName(cacheName),
|
|
370
|
-
plugins: [
|
|
371
|
-
...plugins,
|
|
372
|
-
new PrecacheCacheKeyPlugin({
|
|
373
|
-
precacheController: this
|
|
374
|
-
})
|
|
375
|
-
],
|
|
376
|
-
fallbackToNetwork
|
|
377
|
-
});
|
|
378
|
-
// Bind the install and activate methods to the instance.
|
|
379
|
-
this.install = this.install.bind(this);
|
|
380
|
-
this.activate = this.activate.bind(this);
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* The strategy created by this controller and
|
|
384
|
-
* used to cache assets and respond to fetch events.
|
|
385
|
-
*/ get strategy() {
|
|
386
|
-
return this._strategy;
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Adds items to the precache list, removing any duplicates and
|
|
390
|
-
* stores the files in the precache cache when the service
|
|
391
|
-
* worker installs.
|
|
392
|
-
*
|
|
393
|
-
* This method can be called multiple times.
|
|
394
|
-
*
|
|
395
|
-
* @param entries Array of entries to precache.
|
|
396
|
-
*/ precache(entries) {
|
|
397
|
-
this.addToCacheList(entries);
|
|
398
|
-
if (!this._installAndActiveListenersAdded) {
|
|
399
|
-
self.addEventListener("install", this.install);
|
|
400
|
-
self.addEventListener("activate", this.activate);
|
|
401
|
-
this._installAndActiveListenersAdded = true;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* This method will add items to the precache list, removing duplicates
|
|
406
|
-
* and ensuring the information is valid.
|
|
407
|
-
*
|
|
408
|
-
* @param entries Array of entries to precache.
|
|
409
|
-
*/ addToCacheList(entries) {
|
|
410
|
-
if (process.env.NODE_ENV !== "production") {
|
|
411
|
-
internal.assert.isArray(entries, {
|
|
412
|
-
moduleName: "@serwist/precaching",
|
|
413
|
-
className: "PrecacheController",
|
|
414
|
-
funcName: "addToCacheList",
|
|
415
|
-
paramName: "entries"
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
const urlsToWarnAbout = [];
|
|
419
|
-
for (const entry of entries){
|
|
420
|
-
// See https://github.com/GoogleChrome/workbox/issues/2259
|
|
421
|
-
if (typeof entry === "string") {
|
|
422
|
-
urlsToWarnAbout.push(entry);
|
|
423
|
-
} else if (entry && entry.revision === undefined) {
|
|
424
|
-
urlsToWarnAbout.push(entry.url);
|
|
425
|
-
}
|
|
426
|
-
const { cacheKey, url } = createCacheKey(entry);
|
|
427
|
-
const cacheMode = typeof entry !== "string" && entry.revision ? "reload" : "default";
|
|
428
|
-
if (this._urlsToCacheKeys.has(url) && this._urlsToCacheKeys.get(url) !== cacheKey) {
|
|
429
|
-
throw new internal.SerwistError("add-to-cache-list-conflicting-entries", {
|
|
430
|
-
firstEntry: this._urlsToCacheKeys.get(url),
|
|
431
|
-
secondEntry: cacheKey
|
|
432
|
-
});
|
|
433
|
-
}
|
|
434
|
-
if (typeof entry !== "string" && entry.integrity) {
|
|
435
|
-
if (this._cacheKeysToIntegrities.has(cacheKey) && this._cacheKeysToIntegrities.get(cacheKey) !== entry.integrity) {
|
|
436
|
-
throw new internal.SerwistError("add-to-cache-list-conflicting-integrities", {
|
|
437
|
-
url
|
|
438
|
-
});
|
|
439
|
-
}
|
|
440
|
-
this._cacheKeysToIntegrities.set(cacheKey, entry.integrity);
|
|
441
|
-
}
|
|
442
|
-
this._urlsToCacheKeys.set(url, cacheKey);
|
|
443
|
-
this._urlsToCacheModes.set(url, cacheMode);
|
|
444
|
-
if (urlsToWarnAbout.length > 0) {
|
|
445
|
-
const warningMessage = `Serwist is precaching URLs without revision info: ${urlsToWarnAbout.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;
|
|
446
|
-
if (process.env.NODE_ENV === "production") {
|
|
447
|
-
// Use console directly to display this warning without bloating
|
|
448
|
-
// bundle sizes by pulling in all of the logger codebase in prod.
|
|
449
|
-
console.warn(warningMessage);
|
|
450
|
-
} else {
|
|
451
|
-
internal.logger.warn(warningMessage);
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
/**
|
|
457
|
-
* Precaches new and updated assets. Call this method from the service worker
|
|
458
|
-
* install event.
|
|
459
|
-
*
|
|
460
|
-
* Note: this method calls `event.waitUntil()` for you, so you do not need
|
|
461
|
-
* to call it yourself in your event handlers.
|
|
462
|
-
*
|
|
463
|
-
* @param event
|
|
464
|
-
* @returns
|
|
465
|
-
*/ install(event) {
|
|
466
|
-
// waitUntil returns Promise<any>
|
|
467
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
468
|
-
return internal.waitUntil(event, async ()=>{
|
|
469
|
-
const installReportPlugin = new PrecacheInstallReportPlugin();
|
|
470
|
-
this.strategy.plugins.push(installReportPlugin);
|
|
471
|
-
// Cache entries one at a time.
|
|
472
|
-
// See https://github.com/GoogleChrome/workbox/issues/2528
|
|
473
|
-
for (const [url, cacheKey] of this._urlsToCacheKeys){
|
|
474
|
-
const integrity = this._cacheKeysToIntegrities.get(cacheKey);
|
|
475
|
-
const cacheMode = this._urlsToCacheModes.get(url);
|
|
476
|
-
const request = new Request(url, {
|
|
477
|
-
integrity,
|
|
478
|
-
cache: cacheMode,
|
|
479
|
-
credentials: "same-origin"
|
|
480
|
-
});
|
|
481
|
-
await Promise.all(this.strategy.handleAll({
|
|
482
|
-
params: {
|
|
483
|
-
cacheKey
|
|
484
|
-
},
|
|
485
|
-
request,
|
|
486
|
-
event
|
|
487
|
-
}));
|
|
488
|
-
}
|
|
489
|
-
const { updatedURLs, notUpdatedURLs } = installReportPlugin;
|
|
490
|
-
if (process.env.NODE_ENV !== "production") {
|
|
491
|
-
printInstallDetails(updatedURLs, notUpdatedURLs);
|
|
492
|
-
}
|
|
493
|
-
return {
|
|
494
|
-
updatedURLs,
|
|
495
|
-
notUpdatedURLs
|
|
496
|
-
};
|
|
497
|
-
});
|
|
498
|
-
}
|
|
499
|
-
/**
|
|
500
|
-
* Deletes assets that are no longer present in the current precache manifest.
|
|
501
|
-
* Call this method from the service worker activate event.
|
|
502
|
-
*
|
|
503
|
-
* Note: this method calls `event.waitUntil()` for you, so you do not need
|
|
504
|
-
* to call it yourself in your event handlers.
|
|
505
|
-
*
|
|
506
|
-
* @param event
|
|
507
|
-
* @returns
|
|
508
|
-
*/ activate(event) {
|
|
509
|
-
// waitUntil returns Promise<any>
|
|
510
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
511
|
-
return internal.waitUntil(event, async ()=>{
|
|
512
|
-
const cache = await self.caches.open(this.strategy.cacheName);
|
|
513
|
-
const currentlyCachedRequests = await cache.keys();
|
|
514
|
-
const expectedCacheKeys = new Set(this._urlsToCacheKeys.values());
|
|
515
|
-
const deletedURLs = [];
|
|
516
|
-
for (const request of currentlyCachedRequests){
|
|
517
|
-
if (!expectedCacheKeys.has(request.url)) {
|
|
518
|
-
await cache.delete(request);
|
|
519
|
-
deletedURLs.push(request.url);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
if (process.env.NODE_ENV !== "production") {
|
|
523
|
-
printCleanupDetails(deletedURLs);
|
|
524
|
-
}
|
|
525
|
-
return {
|
|
526
|
-
deletedURLs
|
|
527
|
-
};
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
/**
|
|
531
|
-
* Returns a mapping of a precached URL to the corresponding cache key, taking
|
|
532
|
-
* into account the revision information for the URL.
|
|
533
|
-
*
|
|
534
|
-
* @returns A URL to cache key mapping.
|
|
535
|
-
*/ getURLsToCacheKeys() {
|
|
536
|
-
return this._urlsToCacheKeys;
|
|
537
|
-
}
|
|
538
|
-
/**
|
|
539
|
-
* Returns a list of all the URLs that have been precached by the current
|
|
540
|
-
* service worker.
|
|
541
|
-
*
|
|
542
|
-
* @returns The precached URLs.
|
|
543
|
-
*/ getCachedURLs() {
|
|
544
|
-
return [
|
|
545
|
-
...this._urlsToCacheKeys.keys()
|
|
546
|
-
];
|
|
547
|
-
}
|
|
548
|
-
/**
|
|
549
|
-
* Returns the cache key used for storing a given URL. If that URL is
|
|
550
|
-
* unversioned, like `/index.html', then the cache key will be the original
|
|
551
|
-
* URL with a search parameter appended to it.
|
|
552
|
-
*
|
|
553
|
-
* @param url A URL whose cache key you want to look up.
|
|
554
|
-
* @returns The versioned URL that corresponds to a cache key
|
|
555
|
-
* for the original URL, or undefined if that URL isn't precached.
|
|
556
|
-
*/ getCacheKeyForURL(url) {
|
|
557
|
-
const urlObject = new URL(url, location.href);
|
|
558
|
-
return this._urlsToCacheKeys.get(urlObject.href);
|
|
559
|
-
}
|
|
560
|
-
/**
|
|
561
|
-
* @param url A cache key whose SRI you want to look up.
|
|
562
|
-
* @returns The subresource integrity associated with the cache key,
|
|
563
|
-
* or undefined if it's not set.
|
|
564
|
-
*/ getIntegrityForCacheKey(cacheKey) {
|
|
565
|
-
return this._cacheKeysToIntegrities.get(cacheKey);
|
|
566
|
-
}
|
|
567
|
-
/**
|
|
568
|
-
* This acts as a drop-in replacement for
|
|
569
|
-
* [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
|
|
570
|
-
* with the following differences:
|
|
571
|
-
*
|
|
572
|
-
* - It knows what the name of the precache is, and only checks in that cache.
|
|
573
|
-
* - It allows you to pass in an "original" URL without versioning parameters,
|
|
574
|
-
* and it will automatically look up the correct cache key for the currently
|
|
575
|
-
* active revision of that URL.
|
|
576
|
-
*
|
|
577
|
-
* E.g., `matchPrecache('index.html')` will find the correct precached
|
|
578
|
-
* response for the currently active service worker, even if the actual cache
|
|
579
|
-
* key is `'/index.html?__WB_REVISION__=1234abcd'`.
|
|
580
|
-
*
|
|
581
|
-
* @param request The key (without revisioning parameters)
|
|
582
|
-
* to look up in the precache.
|
|
583
|
-
* @returns
|
|
584
|
-
*/ async matchPrecache(request) {
|
|
585
|
-
const url = request instanceof Request ? request.url : request;
|
|
586
|
-
const cacheKey = this.getCacheKeyForURL(url);
|
|
587
|
-
if (cacheKey) {
|
|
588
|
-
const cache = await self.caches.open(this.strategy.cacheName);
|
|
589
|
-
return cache.match(cacheKey);
|
|
590
|
-
}
|
|
591
|
-
return undefined;
|
|
592
|
-
}
|
|
593
|
-
/**
|
|
594
|
-
* Returns a function that looks up `url` in the precache (taking into
|
|
595
|
-
* account revision information), and returns the corresponding `Response`.
|
|
596
|
-
*
|
|
597
|
-
* @param url The precached URL which will be used to lookup the response.
|
|
598
|
-
* @return
|
|
599
|
-
*/ createHandlerBoundToURL(url) {
|
|
600
|
-
const cacheKey = this.getCacheKeyForURL(url);
|
|
601
|
-
if (!cacheKey) {
|
|
602
|
-
throw new internal.SerwistError("non-precached-url", {
|
|
603
|
-
url
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
return (options)=>{
|
|
607
|
-
options.request = new Request(url);
|
|
608
|
-
options.params = {
|
|
609
|
-
cacheKey,
|
|
610
|
-
...options.params
|
|
611
|
-
};
|
|
612
|
-
return this.strategy.handle(options);
|
|
613
|
-
};
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
let precacheController;
|
|
618
|
-
/**
|
|
619
|
-
* @returns
|
|
620
|
-
* @private
|
|
621
|
-
*/ const getOrCreatePrecacheController = ()=>{
|
|
622
|
-
if (!precacheController) {
|
|
623
|
-
precacheController = new PrecacheController();
|
|
624
|
-
}
|
|
625
|
-
return precacheController;
|
|
626
|
-
};
|
|
627
|
-
|
|
628
|
-
/**
|
|
629
|
-
* `PrecacheFallbackPlugin` allows you to specify an "offline fallback"
|
|
630
|
-
* response to be used when a given strategy is unable to generate a response.
|
|
631
|
-
*
|
|
632
|
-
* It does this by intercepting the `handlerDidError` plugin callback
|
|
633
|
-
* and returning a precached response, taking the expected revision parameter
|
|
634
|
-
* into account automatically.
|
|
635
|
-
*
|
|
636
|
-
* Unless you explicitly pass in a `PrecacheController` instance to the
|
|
637
|
-
* constructor, the default instance will be used. Generally speaking, most
|
|
638
|
-
* developers will end up using the default.
|
|
639
|
-
*/ class PrecacheFallbackPlugin {
|
|
640
|
-
_fallbackURL;
|
|
641
|
-
_precacheController;
|
|
642
|
-
/**
|
|
643
|
-
* Constructs a new PrecacheFallbackPlugin with the associated fallbackURL.
|
|
644
|
-
*
|
|
645
|
-
* @param config
|
|
646
|
-
*/ constructor({ fallbackURL, precacheController }){
|
|
647
|
-
this._fallbackURL = fallbackURL;
|
|
648
|
-
this._precacheController = precacheController || getOrCreatePrecacheController();
|
|
649
|
-
}
|
|
650
|
-
/**
|
|
651
|
-
* @returns The precache response for the fallback URL.
|
|
652
|
-
* @private
|
|
653
|
-
*/ handlerDidError = ()=>this._precacheController.matchPrecache(this._fallbackURL);
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
/*
|
|
657
|
-
Copyright 2018 Google LLC
|
|
658
|
-
|
|
659
|
-
Use of this source code is governed by an MIT-style
|
|
660
|
-
license that can be found in the LICENSE file or at
|
|
661
|
-
https://opensource.org/licenses/MIT.
|
|
662
|
-
*/ /**
|
|
663
|
-
* Removes any URL search parameters that should be ignored.
|
|
664
|
-
*
|
|
665
|
-
* @param urlObject The original URL.
|
|
666
|
-
* @param ignoreURLParametersMatching RegExps to test against
|
|
667
|
-
* each search parameter name. Matches mean that the search parameter should be
|
|
668
|
-
* ignored.
|
|
669
|
-
* @returns The URL with any ignored search parameters removed.
|
|
670
|
-
* @private
|
|
671
|
-
*/ function removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching = []) {
|
|
672
|
-
// Convert the iterable into an array at the start of the loop to make sure
|
|
673
|
-
// deletion doesn't mess up iteration.
|
|
674
|
-
for (const paramName of [
|
|
675
|
-
...urlObject.searchParams.keys()
|
|
676
|
-
]){
|
|
677
|
-
if (ignoreURLParametersMatching.some((regExp)=>regExp.test(paramName))) {
|
|
678
|
-
urlObject.searchParams.delete(paramName);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
return urlObject;
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
/**
|
|
685
|
-
* Generator function that yields possible variations on the original URL to
|
|
686
|
-
* check, one at a time.
|
|
687
|
-
*
|
|
688
|
-
* @param url
|
|
689
|
-
* @param options
|
|
690
|
-
*
|
|
691
|
-
* @private
|
|
692
|
-
*/ function* generateURLVariations(url, { ignoreURLParametersMatching = [
|
|
693
|
-
/^utm_/,
|
|
694
|
-
/^fbclid$/
|
|
695
|
-
], directoryIndex = "index.html", cleanURLs = true, urlManipulation } = {}) {
|
|
696
|
-
const urlObject = new URL(url, location.href);
|
|
697
|
-
urlObject.hash = "";
|
|
698
|
-
yield urlObject.href;
|
|
699
|
-
const urlWithoutIgnoredParams = removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching);
|
|
700
|
-
yield urlWithoutIgnoredParams.href;
|
|
701
|
-
if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith("/")) {
|
|
702
|
-
const directoryURL = new URL(urlWithoutIgnoredParams.href);
|
|
703
|
-
directoryURL.pathname += directoryIndex;
|
|
704
|
-
yield directoryURL.href;
|
|
705
|
-
}
|
|
706
|
-
if (cleanURLs) {
|
|
707
|
-
const cleanURL = new URL(urlWithoutIgnoredParams.href);
|
|
708
|
-
cleanURL.pathname += ".html";
|
|
709
|
-
yield cleanURL.href;
|
|
710
|
-
}
|
|
711
|
-
if (urlManipulation) {
|
|
712
|
-
const additionalURLs = urlManipulation({
|
|
713
|
-
url: urlObject
|
|
714
|
-
});
|
|
715
|
-
for (const urlToAttempt of additionalURLs){
|
|
716
|
-
yield urlToAttempt.href;
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
/**
|
|
722
|
-
* A subclass of `@serwist/routing.Route` that takes a
|
|
723
|
-
* `@serwist/precaching.PrecacheController`
|
|
724
|
-
* instance and uses it to match incoming requests and handle fetching
|
|
725
|
-
* responses from the precache.
|
|
726
|
-
*/ class PrecacheRoute extends routing.Route {
|
|
727
|
-
/**
|
|
728
|
-
* @param precacheController A `PrecacheController`
|
|
729
|
-
* instance used to both match requests and respond to fetch events.
|
|
730
|
-
* @param options Options to control how requests are matched
|
|
731
|
-
* against the list of precached URLs.
|
|
732
|
-
*/ constructor(precacheController, options){
|
|
733
|
-
const match = ({ request })=>{
|
|
734
|
-
const urlsToCacheKeys = precacheController.getURLsToCacheKeys();
|
|
735
|
-
for (const possibleURL of generateURLVariations(request.url, options)){
|
|
736
|
-
const cacheKey = urlsToCacheKeys.get(possibleURL);
|
|
737
|
-
if (cacheKey) {
|
|
738
|
-
const integrity = precacheController.getIntegrityForCacheKey(cacheKey);
|
|
739
|
-
return {
|
|
740
|
-
cacheKey,
|
|
741
|
-
integrity
|
|
742
|
-
};
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
if (process.env.NODE_ENV !== "production") {
|
|
746
|
-
internal.logger.debug(`Precaching did not find a match for ${internal.getFriendlyURL(request.url)}`);
|
|
747
|
-
}
|
|
748
|
-
return;
|
|
749
|
-
};
|
|
750
|
-
super(match, precacheController.strategy);
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
/**
|
|
755
|
-
* Adds plugins to the precaching strategy.
|
|
756
|
-
*
|
|
757
|
-
* @param plugins
|
|
758
|
-
*/ function addPlugins(plugins) {
|
|
759
|
-
const precacheController = getOrCreatePrecacheController();
|
|
760
|
-
precacheController.strategy.plugins.push(...plugins);
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
/**
|
|
764
|
-
* Add a `fetch` listener to the service worker that will
|
|
765
|
-
* respond to
|
|
766
|
-
* [network requests](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests)
|
|
767
|
-
* with precached assets.
|
|
768
|
-
*
|
|
769
|
-
* Requests for assets that aren't precached, the `FetchEvent` will not be
|
|
770
|
-
* responded to, allowing the event to fall through to other `fetch` event
|
|
771
|
-
* listeners.
|
|
772
|
-
*
|
|
773
|
-
* @param options See the `@serwist/precaching.PrecacheRoute` options.
|
|
774
|
-
*/ function addRoute(options) {
|
|
775
|
-
const precacheController = getOrCreatePrecacheController();
|
|
776
|
-
const precacheRoute = new PrecacheRoute(precacheController, options);
|
|
777
|
-
routing.registerRoute(precacheRoute);
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
/*
|
|
781
|
-
Copyright 2018 Google LLC
|
|
782
|
-
|
|
783
|
-
Use of this source code is governed by an MIT-style
|
|
784
|
-
license that can be found in the LICENSE file or at
|
|
785
|
-
https://opensource.org/licenses/MIT.
|
|
786
|
-
*/ // Give TypeScript the correct global.
|
|
787
|
-
const SUBSTRING_TO_FIND = "-precache-";
|
|
788
|
-
/**
|
|
789
|
-
* Cleans up incompatible precaches that were created by older versions of
|
|
790
|
-
* Serwist, by a service worker registered under the current scope.
|
|
791
|
-
*
|
|
792
|
-
* This is meant to be called as part of the `activate` event.
|
|
793
|
-
*
|
|
794
|
-
* This should be safe to use as long as you don't include `substringToFind`
|
|
795
|
-
* (defaulting to `-precache-`) in your non-precache cache names.
|
|
796
|
-
*
|
|
797
|
-
* @param currentPrecacheName The cache name currently in use for
|
|
798
|
-
* precaching. This cache won't be deleted.
|
|
799
|
-
* @param substringToFind Cache names which include this
|
|
800
|
-
* substring will be deleted (excluding `currentPrecacheName`).
|
|
801
|
-
* @returns A list of all the cache names that were deleted.
|
|
802
|
-
* @private
|
|
803
|
-
*/ const deleteOutdatedCaches = async (currentPrecacheName, substringToFind = SUBSTRING_TO_FIND)=>{
|
|
804
|
-
const cacheNames = await self.caches.keys();
|
|
805
|
-
const cacheNamesToDelete = cacheNames.filter((cacheName)=>{
|
|
806
|
-
return cacheName.includes(substringToFind) && cacheName.includes(self.registration.scope) && cacheName !== currentPrecacheName;
|
|
807
|
-
});
|
|
808
|
-
await Promise.all(cacheNamesToDelete.map((cacheName)=>self.caches.delete(cacheName)));
|
|
809
|
-
return cacheNamesToDelete;
|
|
810
|
-
};
|
|
811
|
-
|
|
812
|
-
/**
|
|
813
|
-
* Adds an `activate` event listener which will clean up incompatible
|
|
814
|
-
* precaches that were created by older versions of Serwist.
|
|
815
|
-
*/ function cleanupOutdatedCaches() {
|
|
816
|
-
// See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
|
|
817
|
-
self.addEventListener("activate", (event)=>{
|
|
818
|
-
const cacheName = internal.privateCacheNames.getPrecacheName();
|
|
819
|
-
event.waitUntil(deleteOutdatedCaches(cacheName).then((cachesDeleted)=>{
|
|
820
|
-
if (process.env.NODE_ENV !== "production") {
|
|
821
|
-
if (cachesDeleted.length > 0) {
|
|
822
|
-
internal.logger.log("The following out-of-date precaches were cleaned up " + "automatically:", cachesDeleted);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
}));
|
|
826
|
-
});
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
/**
|
|
830
|
-
* Helper function that calls `PrecacheController#createHandlerBoundToURL`
|
|
831
|
-
* on the default `PrecacheController` instance.
|
|
832
|
-
*
|
|
833
|
-
* If you are creating your own `PrecacheController`, then call the
|
|
834
|
-
* `PrecacheController#createHandlerBoundToURL` on that instance,
|
|
835
|
-
* instead of using this function.
|
|
836
|
-
*
|
|
837
|
-
* @param url The precached URL which will be used to lookup the
|
|
838
|
-
* `Response`.
|
|
839
|
-
* @param fallbackToNetwork Whether to attempt to get the
|
|
840
|
-
* response from the network if there's a precache miss.
|
|
841
|
-
* @return
|
|
842
|
-
*/ function createHandlerBoundToURL(url) {
|
|
843
|
-
const precacheController = getOrCreatePrecacheController();
|
|
844
|
-
return precacheController.createHandlerBoundToURL(url);
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
/**
|
|
848
|
-
* Takes in a URL, and returns the corresponding URL that could be used to
|
|
849
|
-
* lookup the entry in the precache.
|
|
850
|
-
*
|
|
851
|
-
* If a relative URL is provided, the location of the service worker file will
|
|
852
|
-
* be used as the base.
|
|
853
|
-
*
|
|
854
|
-
* For precached entries without revision information, the cache key will be the
|
|
855
|
-
* same as the original URL.
|
|
856
|
-
*
|
|
857
|
-
* For precached entries with revision information, the cache key will be the
|
|
858
|
-
* original URL with the addition of a query parameter used for keeping track of
|
|
859
|
-
* the revision info.
|
|
860
|
-
*
|
|
861
|
-
* @param url The URL whose cache key to look up.
|
|
862
|
-
* @returns The cache key that corresponds to that URL.
|
|
863
|
-
*/ function getCacheKeyForURL(url) {
|
|
864
|
-
const precacheController = getOrCreatePrecacheController();
|
|
865
|
-
return precacheController.getCacheKeyForURL(url);
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
/**
|
|
869
|
-
* Helper function that calls `PrecacheController#matchPrecache`
|
|
870
|
-
* on the default `PrecacheController` instance.
|
|
871
|
-
*
|
|
872
|
-
* If you are creating your own `PrecacheController`, then call
|
|
873
|
-
* `PrecacheController#matchPrecache` on that instance,
|
|
874
|
-
* instead of using this function.
|
|
875
|
-
*
|
|
876
|
-
* @param request The key (without revisioning parameters)
|
|
877
|
-
* to look up in the precache.
|
|
878
|
-
* @returns
|
|
879
|
-
*/ function matchPrecache(request) {
|
|
880
|
-
const precacheController = getOrCreatePrecacheController();
|
|
881
|
-
return precacheController.matchPrecache(request);
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
/**
|
|
885
|
-
* Adds items to the precache list, removing any duplicates and
|
|
886
|
-
* stores the files in the precache cache when the service
|
|
887
|
-
* worker installs.
|
|
888
|
-
*
|
|
889
|
-
* This method can be called multiple times.
|
|
890
|
-
*
|
|
891
|
-
* Please note: This method **will not** serve any of the cached files for you.
|
|
892
|
-
* It only precaches files. To respond to a network request you call
|
|
893
|
-
* `@serwist/precaching.addRoute`.
|
|
894
|
-
*
|
|
895
|
-
* If you have a single array of files to precache, you can just call
|
|
896
|
-
* `@serwist/precaching.precacheAndRoute`.
|
|
897
|
-
*
|
|
898
|
-
* @param entries Array of entries to precache.
|
|
899
|
-
*/ function precache(entries) {
|
|
900
|
-
const precacheController = getOrCreatePrecacheController();
|
|
901
|
-
precacheController.precache(entries);
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
/**
|
|
905
|
-
* This method will add entries to the precache list and add a route to
|
|
906
|
-
* respond to fetch events.
|
|
907
|
-
*
|
|
908
|
-
* This is a convenience method that will call
|
|
909
|
-
* `@serwist/precaching.precache` and
|
|
910
|
-
* `@serwist/precaching.addRoute` in a single call.
|
|
911
|
-
*
|
|
912
|
-
* @param entries Array of entries to precache.
|
|
913
|
-
* @param options See the `@serwist/precaching.PrecacheRoute` options.
|
|
914
|
-
*/ function precacheAndRoute(entries, options) {
|
|
915
|
-
precache(entries);
|
|
916
|
-
addRoute(options);
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
exports.PrecacheController = PrecacheController;
|
|
920
|
-
exports.PrecacheFallbackPlugin = PrecacheFallbackPlugin;
|
|
921
|
-
exports.PrecacheRoute = PrecacheRoute;
|
|
922
|
-
exports.PrecacheStrategy = PrecacheStrategy;
|
|
923
|
-
exports.addPlugins = addPlugins;
|
|
924
|
-
exports.addRoute = addRoute;
|
|
925
|
-
exports.cleanupOutdatedCaches = cleanupOutdatedCaches;
|
|
926
|
-
exports.createHandlerBoundToURL = createHandlerBoundToURL;
|
|
927
|
-
exports.getCacheKeyForURL = getCacheKeyForURL;
|
|
928
|
-
exports.matchPrecache = matchPrecache;
|
|
929
|
-
exports.precache = precache;
|
|
930
|
-
exports.precacheAndRoute = precacheAndRoute;
|