Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New precache helper functions + removal of createHandlerForURL #2254

Merged
merged 3 commits into from
Oct 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion infra/testing/validator/service-worker-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ function setupSpiesAndContextForGenerateSW() {
importScripts,
CacheFirst: sinon.stub().returns({name: 'CacheFirst'}),
clientsClaim: sinon.spy(),
createHandlerForURL: sinon.stub().returns('/urlWithCacheKey'),
createHandlerBoundToURL: sinon.stub().returns('/urlWithCacheKey'),
enable: sinon.spy(),
initialize: sinon.spy(),
NavigationRoute: sinon.stub().returns({name: 'NavigationRoute'}),
Expand Down
2 changes: 1 addition & 1 deletion packages/workbox-build/src/templates/sw-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ self.addEventListener('message', (event) => {
*/
<%= use('workbox-precaching', 'precacheAndRoute') %>(<%= JSON.stringify(manifestEntries, null, 2) %>, <%= precacheOptionsString %>);
<% if (cleanupOutdatedCaches) { %><%= use('workbox-precaching', 'cleanupOutdatedCaches') %>();<% } %>
<% if (navigateFallback) { %><%= use('workbox-routing', 'registerRoute') %>(new <%= use('workbox-routing', 'NavigationRoute') %>(<%= use('workbox-precaching', 'createHandlerForURL') %>(<%= JSON.stringify(navigateFallback) %>)<% if (navigateFallbackWhitelist || navigateFallbackBlacklist) { %>, {
<% if (navigateFallback) { %><%= use('workbox-routing', 'registerRoute') %>(new <%= use('workbox-routing', 'NavigationRoute') %>(<%= use('workbox-precaching', 'createHandlerBoundToURL') %>(<%= JSON.stringify(navigateFallback) %>)<% if (navigateFallbackWhitelist || navigateFallbackBlacklist) { %>, {
<% if (navigateFallbackWhitelist) { %>whitelist: [<%= navigateFallbackWhitelist %>],<% } %>
<% if (navigateFallbackBlacklist) { %>blacklist: [<%= navigateFallbackBlacklist %>],<% } %>
}<% } %>));<% } %>
Expand Down
8 changes: 6 additions & 2 deletions packages/workbox-core/src/models/messages/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,17 @@ export const messages : MessageMap = {
},

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

'add-to-cache-list-conflicting-integrities': ({url}) => {
return `Two of the entries passed to ` +
`'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` +
`${url} with different integrity values. Please remove one of them.`;
},

'missing-precache-entry': ({cacheName, url}) => {
return `Unable to find a precached response in ${cacheName} for ${url}.`;
},
};
113 changes: 76 additions & 37 deletions packages/workbox-precaching/src/PrecacheController.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2018 Google LLC
Copyright 2019 Google LLC

Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
Expand All @@ -13,7 +13,8 @@ import {fetchWrapper} from 'workbox-core/_private/fetchWrapper.js';
import {logger} from 'workbox-core/_private/logger.js';
import {WorkboxError} from 'workbox-core/_private/WorkboxError.js';
import {copyResponse} from 'workbox-core/copyResponse.js';
import {RouteHandlerCallback} from 'workbox-core/types.js';
import {RouteHandlerCallback, RouteHandlerCallbackOptions}
from 'workbox-core/types.js';
import {WorkboxPlugin} from 'workbox-core/types.js';

import {PrecacheEntry} from './_types.js';
Expand Down Expand Up @@ -310,58 +311,96 @@ class PrecacheController {
}

/**
* Returns a function that looks up `url` in the precache (taking into
* account revision information), and returns the corresponding `Response`.
* This acts as a drop-in replacement for [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
* with the following differences:
*
* - It knows what the name of the precache is, and only checks in that cache.
* - It allows you to pass in an "original" URL without versioning parameters,
* and it will automatically look up the correct cache key for the currently
* active revision of that URL.
*
* E.g., `matchPrecache('index.html')` will find the correct precached
* response for the currently active service worker, even if the actual cache
* key is `'/index.html?__WB_REVISION__=1234abcd'`.
*
* If for an unexpected reason there is a cache miss when looking up `url`,
* this will fall back to retrieving the `Response` via `fetch()`.
*
* @param {string} url The precached URL which will be used to lookup the
* `Response`.
* @return {workbox.routing.Route~handlerCallback}
* @param {string|Request} request The key (without revisioning parameters)
* to look up in the precache.
* @return {Promise<Response|undefined>}
*/
createHandlerForURL(url: string): RouteHandlerCallback {
if (process.env.NODE_ENV !== 'production') {
assert!.isType(url, 'string', {
moduleName: 'workbox-precaching',
funcName: 'createHandlerForURL',
paramName: 'url',
});
}

async matchPrecache(request: string|Request): Promise<Response|undefined> {
const url = request instanceof Request ? request.url : request;
const cacheKey = this.getCacheKeyForURL(url);
if (!cacheKey) {
throw new WorkboxError('non-precached-url', {url});
if (cacheKey) {
const cache = await caches.open(this._cacheName);
return cache.match(cacheKey);
}
return undefined;
}

return async () => {
/**
* Returns a function that can be used within a {@link workbox.routing.Route}
* that will find a response for the incoming request against the precache.
*
* If for an unexpected reason there is a cache miss for the request,
* this will fall back to retrieving the `Response` via `fetch()` when
* `fallbackToNetwork` is `true`.
*
* @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
* response from the network if there's a precache miss.
* @return {workbox.routing.Route~handlerCallback}
*/
createHandler(fallbackToNetwork = true): RouteHandlerCallback {
return async ({request}: RouteHandlerCallbackOptions) => {
try {
const cache = await caches.open(this._cacheName);
const response = await cache.match(cacheKey);

const response = await this.matchPrecache(request);
if (response) {
return response;
}

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

// This might still fail if the browser is offline...
return fetch(cacheKey);
throw error;
}
};
};
}

/**
* Returns a function that looks up `url` in the precache (taking into
* account revision information), and returns the corresponding `Response`.
*
* If for an unexpected reason there is a cache miss when looking up `url`,
* this will fall back to retrieving the `Response` via `fetch()` when
* `fallbackToNetwork` is `true`.
*
* @param {string} url The precached URL which will be used to lookup the
* `Response`.
* @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
* response from the network if there's a precache miss.
* @return {workbox.routing.Route~handlerCallback}
*/
createHandlerBoundToURL(url: string, fallbackToNetwork = true): RouteHandlerCallback {
const cacheKey = this.getCacheKeyForURL(url);
if (!cacheKey) {
throw new WorkboxError('non-precached-url', {url});
}

const handler = this.createHandler(fallbackToNetwork);
const request = new Request(url);
return () => handler({request});
}
}

export {PrecacheController};
31 changes: 31 additions & 0 deletions packages/workbox-precaching/src/createHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Copyright 2019 Google LLC

Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/

import {getOrCreatePrecacheController} from './utils/getOrCreatePrecacheController.js';

import './_version.js';

/**
* Helper function that calls
* {@link PrecacheController#createHandler} on the default
* {@link PrecacheController} instance.
*
* If you are creating your own {@link PrecacheController}, then call the
* {@link PrecacheController#createHandler} on that instance,
* instead of using this function.
*
* @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
* response from the network if there's a precache miss.
* @return {workbox.routing.Route~handlerCallback}
*
* @alias workbox.precaching.createHandler
*/
export const createHandler = (fallbackToNetwork = true) => {
const precacheController = getOrCreatePrecacheController();
return precacheController.createHandler(fallbackToNetwork);
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,22 @@ import './_version.js';

/**
* Helper function that calls
* {@link PrecacheController#createHandlerForURL} on the default
* {@link PrecacheController#createHandlerBoundToURL} on the default
* {@link PrecacheController} instance.
*
* If you are creating your own {@link PrecacheController}, then call the
* {@link PrecacheController#createHandlerForURL} on that instance,
* {@link PrecacheController#createHandlerBoundToURL} on that instance,
* instead of using this function.
*
* @param {string} url The precached URL which will be used to lookup the
* `Response`.
* @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
* response from the network if there's a precache miss.
* @return {workbox.routing.Route~handlerCallback}
*
* @alias workbox.precaching.createHandlerForURL
* @alias workbox.precaching.createHandlerBoundToURL
*/
export const createHandlerForURL = (url: string) => {
export const createHandlerBoundToURL = (url: string) => {
const precacheController = getOrCreatePrecacheController();
return precacheController.createHandlerForURL(url);
return precacheController.createHandlerBoundToURL(url);
};
11 changes: 8 additions & 3 deletions packages/workbox-precaching/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@
*/

import {assert} from 'workbox-core/_private/assert.js';

import {addPlugins} from './addPlugins.js';
import {addRoute} from './addRoute.js';
import {cleanupOutdatedCaches} from './cleanupOutdatedCaches.js';
import {createHandlerForURL} from './createHandlerForURL.js';
import {createHandler} from './createHandler.js';
import {createHandlerBoundToURL} from './createHandlerBoundToURL.js';
import {getCacheKeyForURL} from './getCacheKeyForURL.js';
import {matchPrecache} from './matchPrecache.js';
import {precache} from './precache.js';
import {precacheAndRoute} from './precacheAndRoute.js';
import {PrecacheController} from './PrecacheController.js';
import './_version.js';

import './_version.js';

if (process.env.NODE_ENV !== 'production') {
assert!.isSWEnv('workbox-precaching');
Expand All @@ -39,8 +42,10 @@ export {
addPlugins,
addRoute,
cleanupOutdatedCaches,
createHandlerForURL,
createHandler,
createHandlerBoundToURL,
getCacheKeyForURL,
matchPrecache,
precache,
precacheAndRoute,
PrecacheController,
Expand Down
31 changes: 31 additions & 0 deletions packages/workbox-precaching/src/matchPrecache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Copyright 2019 Google LLC

Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/

import {getOrCreatePrecacheController} from './utils/getOrCreatePrecacheController.js';

import './_version.js';

/**
* Helper function that calls
* {@link PrecacheController#matchPrecache} on the default
* {@link PrecacheController} instance.
*
* If you are creating your own {@link PrecacheController}, then call
* {@link PrecacheController#matchPrecache} on that instance,
* instead of using this function.
*
* @param {string|Request} request The key (without revisioning parameters)
* to look up in the precache.
* @return {Promise<Response|undefined>}
*
* @alias workbox.precaching.matchPrecache
*/
export const matchPrecache = (request: string|Request) => {
const precacheController = getOrCreatePrecacheController();
return precacheController.matchPrecache(request);
};
2 changes: 1 addition & 1 deletion test/workbox-build/node/generate-sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ describe(`[workbox-build] generate-sw.js (End to End)`, function() {
confirmDirectoryContains(outputDir, filePaths);

await validateServiceWorkerRuntime({swFile: swDest, expectedMethodCalls: {
createHandlerForURL: [[navigateFallback]],
createHandlerBoundToURL: [[navigateFallback]],
importScripts: [],
precacheAndRoute: [[[{
url: 'index.html',
Expand Down
Loading