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

Commit

Permalink
Adds a dontCacheBustUrlsMatching option.
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffposnick committed Jun 15, 2016
1 parent 1ca4494 commit d06def1
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 4 deletions.
28 changes: 28 additions & 0 deletions README.md
Expand Up @@ -31,6 +31,7 @@ The full documentation is in this README, and the
- [Options Parameter](#options-parameter)
- [cacheId [String]](#cacheid-string)
- [directoryIndex [String]](#directoryindex-string)
- [dontCacheBustUrlsMatching [Regex]](#dontcachebusturlsmatching-regex)
- [dynamicUrlToDependencies [Object⟨String,Array⟨String⟩⟩]](#dynamicurltodependencies-objectstringarraystring)
- [handleFetch [boolean]](#handlefetch-boolean)
- [ignoreUrlParametersMatching [Array⟨Regex⟩]](#ignoreurlparametersmatching-arrayregex)
Expand Down Expand Up @@ -260,6 +261,33 @@ mappings between a directory URL and a corresponding file.

_Default_: `'index.html'`

#### dontCacheBustUrlsMatching [Regex]
It's very important that the requests `sw-precache` makes to populate your cache
result in the most up-to-date version of a resource at a given URL. Requests
that are fulfilled with out-of-date responses (like those found in your
browser's HTTP cache) can end up being read from the service worker's cache
indefinitely. Jake Archibald's [blog post](https://jakearchibald.com/2016/caching-best-practices/#a-service-worker-can-extend-the-life-of-these-bugs)
provides more context about this problem.

In the interest of avoiding that scenario, `sw-precache` will, by default,
append a cache-busting parameter to the end of each URL it requests when
populating or updating its cache. Developers who are explicitly doing "the right
thing" when it comes to setting HTTP caching headers on their responses might
want to opt out of this cache-busting. For example, if all of your static
resources already include versioning information in their URLs (via a tool like
[`gulp-rev`](https://github.com/sindresorhus/gulp-rev)), and are served with
long-lived HTTP caching headers, then the extra cache-busting URL parameter
is not needed, and can be safely excluded.

`dontCacheBustUrlsMatching` gives you a way of opting-in to skipping the cache
busting behavior for a subset of your URLs (or all of them, if a catch-all value
like `/./` is used).
If set, then each URL that's prefetched will be matched against this value.
If there's a match, then the URL will be prefetched as-is, without an additional
cache-busting URL parameter appended.

_Default_: not set

#### dynamicUrlToDependencies [Object⟨String,Array⟨String⟩⟩]
Maps a dynamic URL string to an array of all the files that URL's contents
depend on. E.g., if the contents of `/pages/home` are generated server-side via
Expand Down
14 changes: 11 additions & 3 deletions lib/functions.js
Expand Up @@ -63,11 +63,19 @@ module.exports = {
});
},

createCacheKey: function(originalUrl, paramName, paramValue) {
createCacheKey: function(originalUrl, paramName, paramValue,
dontCacheBustUrlsMatching) {
// Create a new URL object to avoid modifying originalUrl.
var url = new URL(originalUrl);
url.search += (url.search ? '&' : '') +
encodeURIComponent(paramName) + '=' + encodeURIComponent(paramValue);

// If dontCacheBustUrlsMatching is not set, or if we don't have a match,
// then add in the extra cache-busting URL parameter.
if (!dontCacheBustUrlsMatching ||
!(url.toString().match(dontCacheBustUrlsMatching))) {
url.search += (url.search ? '&' : '') +
encodeURIComponent(paramName) + '=' + encodeURIComponent(paramValue);
}

return url.toString();
}
};
2 changes: 2 additions & 0 deletions lib/sw-precache.js
Expand Up @@ -79,6 +79,7 @@ function generate(params, callback) {
params = defaults(params || {}, {
cacheId: '',
directoryIndex: 'index.html',
dontCacheBustUrlsMatching: null,
dynamicUrlToDependencies: {},
handleFetch: true,
ignoreUrlParametersMatching: [/^utm_/],
Expand Down Expand Up @@ -245,6 +246,7 @@ function generate(params, callback) {
cacheId: params.cacheId,
// Ensure that anything false is translated into '', since this will be treated as a string.
directoryIndex: params.directoryIndex || '',
dontCacheBustUrlsMatching: params.dontCacheBustUrlsMatching || false,
externalFunctions: externalFunctions,
handleFetch: params.handleFetch,
ignoreUrlParametersMatching: params.ignoreUrlParametersMatching,
Expand Down
2 changes: 1 addition & 1 deletion service-worker.tmpl
Expand Up @@ -41,7 +41,7 @@ var urlsToCacheKeys = new Map(
var relativeUrl = item[0];
var hash = item[1];
var absoluteUrl = new URL(relativeUrl, self.location);
var cacheKey = createCacheKey(absoluteUrl, hashParamName, hash);
var cacheKey = createCacheKey(absoluteUrl, hashParamName, hash, <%= dontCacheBustUrlsMatching %>);
return [absoluteUrl.toString(), cacheKey];
})
);
Expand Down
14 changes: 14 additions & 0 deletions test/test.js
Expand Up @@ -405,4 +405,18 @@ describe('createCacheKey', function() {
assert.strictEqual(cacheKey, 'http://example.com/test/path?existing=value&name=value');
done();
});

it('should not append the parameter when the URL matches the exclusion pattern', function(done) {
var url = 'http://example.com/test/path?existing=value';
var cacheKey = externalFunctions.createCacheKey(url, 'name', 'value', /example/);
assert.strictEqual(cacheKey, url);
done();
});

it('should append the parameter when the URL does not match the exclusion pattern', function(done) {
var url = 'http://example.com/test/path?existing=value';
var cacheKey = externalFunctions.createCacheKey(url, 'name', 'value', /no_match/);
assert.strictEqual(cacheKey, 'http://example.com/test/path?existing=value&name=value');
done();
});
});

1 comment on commit d06def1

@jeffposnick
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I accidentally pushed this to master instead of a branch 👎

I'm hoping it's non-controversial and can just go in as-is, but CC: @addyosmani @wibblymat @gauntface @jakearchibald to give it a look over. Happy to put together a formal PR with any updates you'd like to see.

Please sign in to comment.