From 03d83d8f708ac72c69d138a399c9fd739c163e0d Mon Sep 17 00:00:00 2001 From: Jeff Posnick Date: Wed, 29 Jul 2015 16:39:42 -0400 Subject: [PATCH 1/3] Use precacheHash in the config file instead of listing precache in the SW URL. --- bootstrap/sw-toolbox-setup.js | 24 +++++++++++++++++--- platinum-sw-cache.html | 29 ++++++++++++++++++++++-- test/platinum-sw-cache/cache-config.json | 3 ++- test/platinum-sw-cache/index.html | 2 +- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/bootstrap/sw-toolbox-setup.js b/bootstrap/sw-toolbox-setup.js index b47f780..b8bbc4e 100644 --- a/bootstrap/sw-toolbox-setup.js +++ b/bootstrap/sw-toolbox-setup.js @@ -21,10 +21,28 @@ var strategy = global.params.get('defaultCacheStrategy'); global.toolbox.router.default = global.toolbox[strategy] || global[strategy]; } - - if (global.params.has('precache')) { - global.toolbox.precache(global.params.get('precache')); + + var precachePromise; + // When precacheHash is present inside the cacheConfigFile JSON, its a signal that instead of + // reading the list of URLs to precache from the service worker's URL parameters, we need to + // instead fetch the JSON file and read the list of precache URLs for there. This works around + // the problem that the list of URLs to precache might be longer than the browser-specific limit + // on the size of a service worker's URL. + if (global.params.has('precacheHash') && global.params.has('cacheConfigFile')) { + precachePromise = global.fetch(global.params.get('cacheConfigFile')).then(function(response) { + return response.json(); + }).then(function(json) { + return json.precache; + }).catch(function(error) { + return []; + }).then(function(precache) { + return precache.concat(global.params.get('precache')); + }) + } else { + precachePromise = Promise.resolve(global.params.get('precache')); } + + global.toolbox.precache(precachePromise); if (global.params.has('route')) { var setsOfRouteParams = global.params.get('route'); diff --git a/platinum-sw-cache.html b/platinum-sw-cache.html index 878fbff..b4b09ea 100644 --- a/platinum-sw-cache.html +++ b/platinum-sw-cache.html @@ -45,13 +45,26 @@ * be concatenated with the values in the JSON file's `precache` property and the set of files * that are precached will be the union of the two. * + * There's one additional option, `precacheHash`, that can be set in the JSON. If using a + * build script that might output a large number of files to precache, its recommended + * that your build script generate a stable hash of the serialized `precache` array, and set + * `precacheHash` equal to that hash. That way, any changes to the list of files in `precache` + * will result in a new `precacheHash` value, and that will trigger the service worker + * update flow, which will in turn take care of precaching the new files. + * If your build script is Node.js based, one way to generate this hash is: + * + * var md5 = require('crypto').createHash('md5'); + * md5.update(JSON.stringify(precache)); + * var precacheHash = md5.digest('hex'); + * * An example file may look like: * * { * "cacheId": "my-cache-id", * "defaultCacheStrategy": "fastest", * "disabled": false, - * "precache": ["file1.html", "file2.css"] + * "precache": ["file1.html", "file2.css"], + * "precacheHash: "HASH_OF_STRINGIFIED_VALUES_IN_PRECACHE" * } */ cacheConfigFile: String, @@ -126,6 +139,7 @@ }; if (this.cacheConfigFile) { + params.cacheConfigFile = this.cacheConfigFile; window.fetch(this.cacheConfigFile).then(function(response) { if (!response.ok) { throw Error('unable to load ' + this.cacheConfigFile); @@ -137,7 +151,18 @@ // Use an empty set of parameters to effectively disable caching. params = {}; } else { - params.precache = params.precache.concat(config.precache); + // If there's a hash of the list of files to precache provided in the config file, + // then copy that over to the params that will be used to construct the service worker + // URL. This works around the issue where a potentially large number of precache + // files could result in a longer URL than a browser will allow. + // The actual list of files to precache (in config.precache) will be dealt by the + // service worker during the install phase, so we can ignore it here. + // See https://github.com/PolymerElements/platinum-sw/issues/53 + if (config.precacheHash) { + params.precacheHash = config.precacheHash; + } else { + params.precache = params.precache.concat(config.precache); + } params.cacheId = config.cacheId || params.cacheId; params.defaultCacheStrategy = config.defaultCacheStrategy || params.defaultCacheStrategy; diff --git a/test/platinum-sw-cache/cache-config.json b/test/platinum-sw-cache/cache-config.json index db233e5..b815e02 100644 --- a/test/platinum-sw-cache/cache-config.json +++ b/test/platinum-sw-cache/cache-config.json @@ -2,5 +2,6 @@ "cacheId": "my-cache-id", "defaultCacheStrategy": "networkOnly", "disabled": false, - "precache": ["listed_in_json1.txt", "listed_in_json2.txt"] + "precache": ["listed_in_json1.txt", "listed_in_json2.txt"], + "precacheHash": "DUMMY_HASH" } diff --git a/test/platinum-sw-cache/index.html b/test/platinum-sw-cache/index.html index 287f0e0..ed5ab52 100644 --- a/test/platinum-sw-cache/index.html +++ b/test/platinum-sw-cache/index.html @@ -33,7 +33,7 @@ suite('Precaching', function() { test('precache results in Cache Storage API entries', function() { return navigator.serviceWorker.ready.then(function() { - window.fetch(swc.cacheConfigFile).then(function(response) { + return window.fetch(swc.cacheConfigFile).then(function(response) { return response.json(); }).then(function(config) { return swc.precache.concat(config.precache); From d6eb7e81d6a7edc484f107d66c1c5d6653d79cb1 Mon Sep 17 00:00:00 2001 From: Jeff Posnick Date: Thu, 30 Jul 2015 14:49:43 -0400 Subject: [PATCH 2/3] =?UTF-8?q?sw-toolbox=20=E2=9E=94=202.0.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 8b2ef97..6d31ca1 100644 --- a/bower.json +++ b/bower.json @@ -26,7 +26,7 @@ ], "dependencies": { "polymer": "Polymer/polymer#^1.0.0", - "sw-toolbox": "^2.0.2" + "sw-toolbox": "^2.0.4" }, "devDependencies": { "iron-component-page": "PolymerElements/iron-component-page#^1.0.2", From 76f666743f40b2d964fde0e599fa801ebe9bdf1c Mon Sep 17 00:00:00 2001 From: Jeff Posnick Date: Fri, 31 Jul 2015 14:45:31 -0400 Subject: [PATCH 3/3] =?UTF-8?q?precacheHash=20=E2=9E=94=20precacheFingerpr?= =?UTF-8?q?int?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bootstrap/sw-toolbox-setup.js | 8 +++---- platinum-sw-cache.html | 29 +++++++++++++++--------- test/platinum-sw-cache/cache-config.json | 2 +- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/bootstrap/sw-toolbox-setup.js b/bootstrap/sw-toolbox-setup.js index b8bbc4e..8d2e6e5 100644 --- a/bootstrap/sw-toolbox-setup.js +++ b/bootstrap/sw-toolbox-setup.js @@ -23,16 +23,16 @@ } var precachePromise; - // When precacheHash is present inside the cacheConfigFile JSON, its a signal that instead of - // reading the list of URLs to precache from the service worker's URL parameters, we need to + // When precacheFingerprint is present inside the cacheConfigFile JSON, its a signal that instead + // of reading the list of URLs to precache from the service worker's URL parameters, we need to // instead fetch the JSON file and read the list of precache URLs for there. This works around // the problem that the list of URLs to precache might be longer than the browser-specific limit // on the size of a service worker's URL. - if (global.params.has('precacheHash') && global.params.has('cacheConfigFile')) { + if (global.params.has('precacheFingerprint') && global.params.has('cacheConfigFile')) { precachePromise = global.fetch(global.params.get('cacheConfigFile')).then(function(response) { return response.json(); }).then(function(json) { - return json.precache; + return json.precache || []; }).catch(function(error) { return []; }).then(function(precache) { diff --git a/platinum-sw-cache.html b/platinum-sw-cache.html index b4b09ea..cc89221 100644 --- a/platinum-sw-cache.html +++ b/platinum-sw-cache.html @@ -45,17 +45,24 @@ * be concatenated with the values in the JSON file's `precache` property and the set of files * that are precached will be the union of the two. * - * There's one additional option, `precacheHash`, that can be set in the JSON. If using a - * build script that might output a large number of files to precache, its recommended - * that your build script generate a stable hash of the serialized `precache` array, and set - * `precacheHash` equal to that hash. That way, any changes to the list of files in `precache` - * will result in a new `precacheHash` value, and that will trigger the service worker - * update flow, which will in turn take care of precaching the new files. + * There's one additional option, `precacheFingerprint`, that can be set in the JSON. If using + * a build script that might output a large number of files to precache, its recommended + * that your build script generate a unique "fingerprint" of the files. Any changes to the + * `precacheFingerprint` value will result in the underlying service worker kicking off the + * process of caching the files listed in `precache`. + * While there are a few different strategies for generating an appropriate + * `precacheFingerprint` value, a process that makes sense is to use a stable hash of the + * serialized `precache` array. That way, any changes to the list of files in `precache` + * will result in a new `precacheFingerprint` value. * If your build script is Node.js based, one way to generate this hash is: * * var md5 = require('crypto').createHash('md5'); * md5.update(JSON.stringify(precache)); - * var precacheHash = md5.digest('hex'); + * var precacheFingerprint = md5.digest('hex'); + * + * Alternatively, you could use something like the + * [SHA-1 signature](http://stackoverflow.com/questions/1161869/how-to-get-sha-of-the-latest-commit-from-remote-git-repository) + * of your latest `git` commit for the `precacheFingerprint` value. * * An example file may look like: * @@ -64,7 +71,7 @@ * "defaultCacheStrategy": "fastest", * "disabled": false, * "precache": ["file1.html", "file2.css"], - * "precacheHash: "HASH_OF_STRINGIFIED_VALUES_IN_PRECACHE" + * "precacheFingerprint": "FINGERPRINT_OF_FILES_IN_PRECACHE" * } */ cacheConfigFile: String, @@ -75,7 +82,7 @@ * in which all the resources will be stored. * * If nothing is provided, the default value set in - * [`sw-toolbox.options.cacheName`](https://github.com/GoogleChrome/sw-toolbox/blob/8763dcc9fbc9352d58f184050e2131c42f7b6d68/lib/options.js#L28) + * [`toolbox.options.cacheName`](https://github.com/GoogleChrome/sw-toolbox/blob/8763dcc9fbc9352d58f184050e2131c42f7b6d68/lib/options.js#L28) * will be used. * * The `cacheId` is combined with the service worker's scope to construct the cache name, so @@ -158,8 +165,8 @@ // The actual list of files to precache (in config.precache) will be dealt by the // service worker during the install phase, so we can ignore it here. // See https://github.com/PolymerElements/platinum-sw/issues/53 - if (config.precacheHash) { - params.precacheHash = config.precacheHash; + if (config.precacheFingerprint) { + params.precacheFingerprint = config.precacheFingerprint; } else { params.precache = params.precache.concat(config.precache); } diff --git a/test/platinum-sw-cache/cache-config.json b/test/platinum-sw-cache/cache-config.json index b815e02..dbb14f3 100644 --- a/test/platinum-sw-cache/cache-config.json +++ b/test/platinum-sw-cache/cache-config.json @@ -3,5 +3,5 @@ "defaultCacheStrategy": "networkOnly", "disabled": false, "precache": ["listed_in_json1.txt", "listed_in_json2.txt"], - "precacheHash": "DUMMY_HASH" + "precacheFingerprint": "DUMMY_HASH" }