Skip to content
This repository has been archived by the owner on Jan 23, 2021. It is now read-only.

Adds a navigateFallbackWhitelist option #85

Merged
merged 4 commits into from
Feb 17, 2016
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
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ The full documentation is in this README, and the
- [logger [function]](#logger-function)
- [maximumFileSizeToCacheInBytes [Number]](#maximumfilesizetocacheinbytes-number)
- [navigateFallback [String]](#navigatefallback-string)
- [navigateFallbackWhitelist [Array⟨RegExp⟩]](#navigatefallbackwhitelist-arrayregexp)
- [replacePrefix [String]](#replaceprefix-string)
- [runtimeCaching [Array⟨Object⟩]](#runtimecaching-arrayobject)
- [staticFileGlobs [Array⟨String⟩]](#staticfileglobs-arraystring)
Expand Down Expand Up @@ -325,6 +326,30 @@ the request is a navigation.

_Default_: `''`

#### navigateFallbackWhitelist [Array⟨RegExp⟩]
Works to limit the effect of `navigateFallback`, so that the fallback only
applies to requests for URLs with paths that match at least one
[`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp).

This option is useful if you want to fallback to the cached App Shell for
certain specific subsections of your site, but not have that behavior apply
to all of your site's URLs.

For example, if you would like to have `navigateFallback` only apply to
navigation requests to URLs whose path begins with `/guide/`
(e.g. `https://example.com/guide/1234`), the following configuration could be
used:

```js
navigateFallback: '/shell',
navigateFallbackWhitelist: [/^\/guide\//]
```

If set to `[]` (the default), the whitelist will be effectively bypassed, and
`navigateFallback` will apply to all navigation requests, regardless of URL.

_Default_: `[]`

#### replacePrefix [String]
Replaces a specified string at the beginning of path URL's at runtime. Use this
option when you are serving static files from a different directory at runtime
Expand Down
3 changes: 2 additions & 1 deletion app-shell-demo/gulpfile.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import rev from 'gulp-rev';
import sass from 'gulp-sass';
import sequence from 'run-sequence';
import source from 'vinyl-source-stream';
import swPrecache from 'sw-precache';
import swPrecache from '../';
import uglify from 'gulp-uglify';

const SRC_DIR = 'src';
Expand Down Expand Up @@ -133,6 +133,7 @@ gulp.task('generate-service-worker', () => {
importScripts: swScripts,
logger: gutil.log,
navigateFallback: '/shell',
navigateFallbackWhitelist: [/^\/guide\//],
staticFileGlobs: [
`${BUILD_DIR}/rev/js/**/*.js`,
`${BUILD_DIR}/rev/styles/all*.css`,
Expand Down
13 changes: 13 additions & 0 deletions lib/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,18 @@ module.exports = {
'sw-precache=' + now;

return urlWithCacheBusting.toString();
},

isPathWhitelisted: function(whitelist, absoluteUrlString) {
// If the whitelist is empty, then consider all URLs to be whitelisted.
if (whitelist.length === 0) {
return true;
}

// Otherwise compare each path regex to the path of the URL passed in.
var path = (new URL(absoluteUrlString)).pathname;
return whitelist.some(function(whitelistedPathRegex) {
return path.match(whitelistedPathRegex);
});
}
};
5 changes: 5 additions & 0 deletions lib/sw-precache.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ function generate(params, callback) {
logger: console.log,
maximumFileSizeToCacheInBytes: 2 * 1024 * 1024, // 2MB
navigateFallback: '',
navigateFallbackWhitelist: [],
stripPrefix: '',
replacePrefix: '',
staticFileGlobs: [],
Expand Down Expand Up @@ -242,6 +243,10 @@ function generate(params, callback) {
params.importScripts.map(JSON.stringify).join(',') : null,
// Ensure that anything false is translated into '', since this will be treated as a string.
navigateFallback: params.navigateFallback || '',
navigateFallbackWhitelist:
JSON.stringify(params.navigateFallbackWhitelist.map(function(regex) {
return regex.source;
})),
precacheConfig: JSON.stringify(precacheConfig),
runtimeCaching: runtimeCaching,
swToolboxCode: swToolboxCode,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sw-precache",
"version": "3.0.0",
"version": "3.1.0",
"description": "Generate service worker code that will precache specific resources.",
"author": {
"name": "Jeff Posnick",
Expand Down
5 changes: 4 additions & 1 deletion service-worker.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ self.addEventListener('fetch', function(event) {
// https://code.google.com/p/chromium/issues/detail?id=540967
// https://bugzilla.mozilla.org/show_bug.cgi?id=1209081
if (!cacheName && navigateFallback && event.request.headers.has('accept') &&
event.request.headers.get('accept').includes('text/html')) {
event.request.headers.get('accept').includes('text/html') &&
/* eslint-disable quotes, comma-spacing */
isPathWhitelisted(<%= navigateFallbackWhitelist %>, event.request.url)) {
/* eslint-enable quotes, comma-spacing */
var navigateFallbackUrl = new URL(navigateFallback, self.location);
cacheName = AbsoluteUrlToCacheName[navigateFallbackUrl.toString()];
}
Expand Down
24 changes: 24 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -429,3 +429,27 @@ describe('getCacheBustedUrl', function() {
done();
});
});

describe('isPathWhitelisted', function() {
var url = 'http://example.com/test/path?one=two';

it('should return true when passed an empty whitelist', function(done) {
assert(externalFunctions.isPathWhitelisted([], url));
done();
});

it('should return true when passed a whitelist matching the url', function(done) {
assert(externalFunctions.isPathWhitelisted([/^\/test\/path$/], url));
done();
});

it('should return false when passed a whitelist not matching the url', function(done) {
assert(!externalFunctions.isPathWhitelisted([/^oops$/], url));
done();
});

it('should return true when passed a whitelist whose second value matches the url', function(done) {
assert(externalFunctions.isPathWhitelisted([/^oops$/, /^\/test\/path$/], url));
done();
});
});