Skip to content

Commit f192965

Browse files
authored
New precache helper functions + removal of createHandlerForURL (#2254)
* New precaching helper methods * A few more changes * WorkboxError + test
1 parent f74b7b6 commit f192965

File tree

12 files changed

+322
-59
lines changed

12 files changed

+322
-59
lines changed

infra/testing/validator/service-worker-runtime.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ function setupSpiesAndContextForGenerateSW() {
109109
importScripts,
110110
CacheFirst: sinon.stub().returns({name: 'CacheFirst'}),
111111
clientsClaim: sinon.spy(),
112-
createHandlerForURL: sinon.stub().returns('/urlWithCacheKey'),
112+
createHandlerBoundToURL: sinon.stub().returns('/urlWithCacheKey'),
113113
enable: sinon.spy(),
114114
initialize: sinon.spy(),
115115
NavigationRoute: sinon.stub().returns({name: 'NavigationRoute'}),

packages/workbox-build/src/templates/sw-template.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ self.addEventListener('message', (event) => {
4747
*/
4848
<%= use('workbox-precaching', 'precacheAndRoute') %>(<%= JSON.stringify(manifestEntries, null, 2) %>, <%= precacheOptionsString %>);
4949
<% if (cleanupOutdatedCaches) { %><%= use('workbox-precaching', 'cleanupOutdatedCaches') %>();<% } %>
50-
<% if (navigateFallback) { %><%= use('workbox-routing', 'registerRoute') %>(new <%= use('workbox-routing', 'NavigationRoute') %>(<%= use('workbox-precaching', 'createHandlerForURL') %>(<%= JSON.stringify(navigateFallback) %>)<% if (navigateFallbackWhitelist || navigateFallbackBlacklist) { %>, {
50+
<% if (navigateFallback) { %><%= use('workbox-routing', 'registerRoute') %>(new <%= use('workbox-routing', 'NavigationRoute') %>(<%= use('workbox-precaching', 'createHandlerBoundToURL') %>(<%= JSON.stringify(navigateFallback) %>)<% if (navigateFallbackWhitelist || navigateFallbackBlacklist) { %>, {
5151
<% if (navigateFallbackWhitelist) { %>whitelist: [<%= navigateFallbackWhitelist %>],<% } %>
5252
<% if (navigateFallbackBlacklist) { %>blacklist: [<%= navigateFallbackBlacklist %>],<% } %>
5353
}<% } %>));<% } %>

packages/workbox-core/src/models/messages/messages.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,13 +258,17 @@ export const messages : MessageMap = {
258258
},
259259

260260
'non-precached-url': ({url}) => {
261-
return `createHandlerForURL('${url}') was called, but that URL is not ` +
262-
`precached. Please pass in a URL that is precached instead.`;
261+
return `createHandlerBoundToURL('${url}') was called, but that URL is ` +
262+
`not precached. Please pass in a URL that is precached instead.`;
263263
},
264264

265265
'add-to-cache-list-conflicting-integrities': ({url}) => {
266266
return `Two of the entries passed to ` +
267267
`'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` +
268268
`${url} with different integrity values. Please remove one of them.`;
269269
},
270+
271+
'missing-precache-entry': ({cacheName, url}) => {
272+
return `Unable to find a precached response in ${cacheName} for ${url}.`;
273+
},
270274
};

packages/workbox-precaching/src/PrecacheController.ts

Lines changed: 76 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2018 Google LLC
2+
Copyright 2019 Google LLC
33
44
Use of this source code is governed by an MIT-style
55
license that can be found in the LICENSE file or at
@@ -13,7 +13,8 @@ import {fetchWrapper} from 'workbox-core/_private/fetchWrapper.js';
1313
import {logger} from 'workbox-core/_private/logger.js';
1414
import {WorkboxError} from 'workbox-core/_private/WorkboxError.js';
1515
import {copyResponse} from 'workbox-core/copyResponse.js';
16-
import {RouteHandlerCallback} from 'workbox-core/types.js';
16+
import {RouteHandlerCallback, RouteHandlerCallbackOptions}
17+
from 'workbox-core/types.js';
1718
import {WorkboxPlugin} from 'workbox-core/types.js';
1819

1920
import {PrecacheEntry} from './_types.js';
@@ -310,58 +311,96 @@ class PrecacheController {
310311
}
311312

312313
/**
313-
* Returns a function that looks up `url` in the precache (taking into
314-
* account revision information), and returns the corresponding `Response`.
314+
* This acts as a drop-in replacement for [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
315+
* with the following differences:
316+
*
317+
* - It knows what the name of the precache is, and only checks in that cache.
318+
* - It allows you to pass in an "original" URL without versioning parameters,
319+
* and it will automatically look up the correct cache key for the currently
320+
* active revision of that URL.
321+
*
322+
* E.g., `matchPrecache('index.html')` will find the correct precached
323+
* response for the currently active service worker, even if the actual cache
324+
* key is `'/index.html?__WB_REVISION__=1234abcd'`.
315325
*
316-
* If for an unexpected reason there is a cache miss when looking up `url`,
317-
* this will fall back to retrieving the `Response` via `fetch()`.
318-
*
319-
* @param {string} url The precached URL which will be used to lookup the
320-
* `Response`.
321-
* @return {workbox.routing.Route~handlerCallback}
326+
* @param {string|Request} request The key (without revisioning parameters)
327+
* to look up in the precache.
328+
* @return {Promise<Response|undefined>}
322329
*/
323-
createHandlerForURL(url: string): RouteHandlerCallback {
324-
if (process.env.NODE_ENV !== 'production') {
325-
assert!.isType(url, 'string', {
326-
moduleName: 'workbox-precaching',
327-
funcName: 'createHandlerForURL',
328-
paramName: 'url',
329-
});
330-
}
331-
330+
async matchPrecache(request: string|Request): Promise<Response|undefined> {
331+
const url = request instanceof Request ? request.url : request;
332332
const cacheKey = this.getCacheKeyForURL(url);
333-
if (!cacheKey) {
334-
throw new WorkboxError('non-precached-url', {url});
333+
if (cacheKey) {
334+
const cache = await caches.open(this._cacheName);
335+
return cache.match(cacheKey);
335336
}
337+
return undefined;
338+
}
336339

337-
return async () => {
340+
/**
341+
* Returns a function that can be used within a {@link workbox.routing.Route}
342+
* that will find a response for the incoming request against the precache.
343+
*
344+
* If for an unexpected reason there is a cache miss for the request,
345+
* this will fall back to retrieving the `Response` via `fetch()` when
346+
* `fallbackToNetwork` is `true`.
347+
*
348+
* @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
349+
* response from the network if there's a precache miss.
350+
* @return {workbox.routing.Route~handlerCallback}
351+
*/
352+
createHandler(fallbackToNetwork = true): RouteHandlerCallback {
353+
return async ({request}: RouteHandlerCallbackOptions) => {
338354
try {
339-
const cache = await caches.open(this._cacheName);
340-
const response = await cache.match(cacheKey);
341-
355+
const response = await this.matchPrecache(request);
342356
if (response) {
343357
return response;
344358
}
345359

346360
// This shouldn't normally happen, but there are edge cases:
347361
// https://github.com/GoogleChrome/workbox/issues/1441
348-
throw new Error(`The cache ${this._cacheName} did not have an entry ` +
349-
`for ${cacheKey}.`);
362+
throw new WorkboxError('missing-precache-entry', {
363+
cacheName: this._cacheName,
364+
url: request.url,
365+
});
350366
} catch (error) {
351-
// If there's either a cache miss, or the caches.match() call threw
352-
// an exception, then attempt to fulfill the navigation request with
353-
// a response from the network rather than leaving the user with a
354-
// failed navigation.
355-
if (process.env.NODE_ENV !== 'production') {
356-
logger.debug(`Unable to respond to navigation request with ` +
357-
`cached response. Falling back to network.`, error);
367+
if (fallbackToNetwork) {
368+
if (process.env.NODE_ENV !== 'production') {
369+
logger.debug(`Unable to respond with precached response. ` +
370+
`Falling back to network.`, error);
371+
}
372+
return fetch(request);
358373
}
359374

360-
// This might still fail if the browser is offline...
361-
return fetch(cacheKey);
375+
throw error;
362376
}
363377
};
364-
};
378+
}
379+
380+
/**
381+
* Returns a function that looks up `url` in the precache (taking into
382+
* account revision information), and returns the corresponding `Response`.
383+
*
384+
* If for an unexpected reason there is a cache miss when looking up `url`,
385+
* this will fall back to retrieving the `Response` via `fetch()` when
386+
* `fallbackToNetwork` is `true`.
387+
*
388+
* @param {string} url The precached URL which will be used to lookup the
389+
* `Response`.
390+
* @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
391+
* response from the network if there's a precache miss.
392+
* @return {workbox.routing.Route~handlerCallback}
393+
*/
394+
createHandlerBoundToURL(url: string, fallbackToNetwork = true): RouteHandlerCallback {
395+
const cacheKey = this.getCacheKeyForURL(url);
396+
if (!cacheKey) {
397+
throw new WorkboxError('non-precached-url', {url});
398+
}
399+
400+
const handler = this.createHandler(fallbackToNetwork);
401+
const request = new Request(url);
402+
return () => handler({request});
403+
}
365404
}
366405

367406
export {PrecacheController};
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
Copyright 2019 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+
*/
8+
9+
import {getOrCreatePrecacheController} from './utils/getOrCreatePrecacheController.js';
10+
11+
import './_version.js';
12+
13+
/**
14+
* Helper function that calls
15+
* {@link PrecacheController#createHandler} on the default
16+
* {@link PrecacheController} instance.
17+
*
18+
* If you are creating your own {@link PrecacheController}, then call the
19+
* {@link PrecacheController#createHandler} on that instance,
20+
* instead of using this function.
21+
*
22+
* @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
23+
* response from the network if there's a precache miss.
24+
* @return {workbox.routing.Route~handlerCallback}
25+
*
26+
* @alias workbox.precaching.createHandler
27+
*/
28+
export const createHandler = (fallbackToNetwork = true) => {
29+
const precacheController = getOrCreatePrecacheController();
30+
return precacheController.createHandler(fallbackToNetwork);
31+
};

packages/workbox-precaching/src/createHandlerForURL.ts renamed to packages/workbox-precaching/src/createHandlerBoundToURL.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,22 @@ import './_version.js';
1212

1313
/**
1414
* Helper function that calls
15-
* {@link PrecacheController#createHandlerForURL} on the default
15+
* {@link PrecacheController#createHandlerBoundToURL} on the default
1616
* {@link PrecacheController} instance.
1717
*
1818
* If you are creating your own {@link PrecacheController}, then call the
19-
* {@link PrecacheController#createHandlerForURL} on that instance,
19+
* {@link PrecacheController#createHandlerBoundToURL} on that instance,
2020
* instead of using this function.
2121
*
2222
* @param {string} url The precached URL which will be used to lookup the
2323
* `Response`.
24+
* @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
25+
* response from the network if there's a precache miss.
2426
* @return {workbox.routing.Route~handlerCallback}
2527
*
26-
* @alias workbox.precaching.createHandlerForURL
28+
* @alias workbox.precaching.createHandlerBoundToURL
2729
*/
28-
export const createHandlerForURL = (url: string) => {
30+
export const createHandlerBoundToURL = (url: string) => {
2931
const precacheController = getOrCreatePrecacheController();
30-
return precacheController.createHandlerForURL(url);
32+
return precacheController.createHandlerBoundToURL(url);
3133
};

packages/workbox-precaching/src/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@
77
*/
88

99
import {assert} from 'workbox-core/_private/assert.js';
10+
1011
import {addPlugins} from './addPlugins.js';
1112
import {addRoute} from './addRoute.js';
1213
import {cleanupOutdatedCaches} from './cleanupOutdatedCaches.js';
13-
import {createHandlerForURL} from './createHandlerForURL.js';
14+
import {createHandler} from './createHandler.js';
15+
import {createHandlerBoundToURL} from './createHandlerBoundToURL.js';
1416
import {getCacheKeyForURL} from './getCacheKeyForURL.js';
17+
import {matchPrecache} from './matchPrecache.js';
1518
import {precache} from './precache.js';
1619
import {precacheAndRoute} from './precacheAndRoute.js';
1720
import {PrecacheController} from './PrecacheController.js';
18-
import './_version.js';
1921

22+
import './_version.js';
2023

2124
if (process.env.NODE_ENV !== 'production') {
2225
assert!.isSWEnv('workbox-precaching');
@@ -39,8 +42,10 @@ export {
3942
addPlugins,
4043
addRoute,
4144
cleanupOutdatedCaches,
42-
createHandlerForURL,
45+
createHandler,
46+
createHandlerBoundToURL,
4347
getCacheKeyForURL,
48+
matchPrecache,
4449
precache,
4550
precacheAndRoute,
4651
PrecacheController,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
Copyright 2019 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+
*/
8+
9+
import {getOrCreatePrecacheController} from './utils/getOrCreatePrecacheController.js';
10+
11+
import './_version.js';
12+
13+
/**
14+
* Helper function that calls
15+
* {@link PrecacheController#matchPrecache} on the default
16+
* {@link PrecacheController} instance.
17+
*
18+
* If you are creating your own {@link PrecacheController}, then call
19+
* {@link PrecacheController#matchPrecache} on that instance,
20+
* instead of using this function.
21+
*
22+
* @param {string|Request} request The key (without revisioning parameters)
23+
* to look up in the precache.
24+
* @return {Promise<Response|undefined>}
25+
*
26+
* @alias workbox.precaching.matchPrecache
27+
*/
28+
export const matchPrecache = (request: string|Request) => {
29+
const precacheController = getOrCreatePrecacheController();
30+
return precacheController.matchPrecache(request);
31+
};

test/workbox-build/node/generate-sw.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ describe(`[workbox-build] generate-sw.js (End to End)`, function() {
370370
confirmDirectoryContains(outputDir, filePaths);
371371

372372
await validateServiceWorkerRuntime({swFile: swDest, expectedMethodCalls: {
373-
createHandlerForURL: [[navigateFallback]],
373+
createHandlerBoundToURL: [[navigateFallback]],
374374
importScripts: [],
375375
precacheAndRoute: [[[{
376376
url: 'index.html',

0 commit comments

Comments
 (0)