Skip to content

Commit

Permalink
Version 0.0.5
Browse files Browse the repository at this point in the history
Changes to use sw-toolbox.
Resolves #12.
Should also address #5
  • Loading branch information
jkleinsc committed Dec 3, 2015
1 parent 2460269 commit 12c7847
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 53 deletions.
9 changes: 6 additions & 3 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
{
"predef": [
"toolbox",
"CACHE_PREFIX",
"CACHE_VERSION",
"Promise",
"Request",
"caches",
"logDebug",
"navigator",
"self",
"caches",
"Promise"
"toolbox"
],
"node": true
}
53 changes: 31 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,45 @@ For more details on ServiceWorker check out the following:
Usage for Ember Cli
-------------------

`npm install --save-dev broccoli-serviceworker`
`ember install broccoli-serviceworker`

###Configuration
By default the service worker will be generated for production builds and the service worker registration logic will be added to your index.html automatically. Additionally, you can further customize broccoli-serviceworker by setting configurations in your environment.js file:
```JavaScript
//app/config/environment.js

ENV.serviceWorker = {
enabled: true,
serviceWorkerFile: "service-worker.js",
excludePaths: ['tests/', 'online.html',],
includePaths: ['/'],
debug: true,
precacheURLs: ['/mystaticresouce'],
excludePaths: ['test.*', 'robots.txt',],
fallback: [
'/online.html offline.html'
'/online.html /offline.html'
],
dynamicCache: [
'/api/todos'
]
],
includeRegistration: true,
serviceWorkerFile: "service-worker.js",
skipWaiting: true
};
```
The following options are available:
* **enabled** - Generate service worker. Defaults to true in production.
* **debug** - Display debug messages in console.
* **precacheURLs** - Array of URLs to precache and always serve from the cache. broccoli-serviceworker will automatically add all Ember app resources (e.g. files in dist) as precached URLs unless explictly excluded in excludePaths.
* **excludePaths** - Array of paths to exclude from precache. Files can be filtered using regular expressions.
```JavaScript
{
excludePaths: ['index.html', new RegExp(/.\.map$/)],
}
```
* **includeRegistration** -- Automatically add the service worker registration script using contentFor to place the script in body-footer. Defaults to true.
* **serviceWorkerFile** - Name of the service worker file to generate. If **includeRegistration** is set to true, this setting is unused. Defaults to *service-worker.js*.
* **fallback** - Array of URLs with fallbacks when the resource isn't available via network or cache.
* **dynamicCache** - List of URLs that should use a network first strategy that falls back to a cached version of the response if the network is unavailable. For more details, see the details on [sw-toolbox's networkFirst strategy](https://github.com/GoogleChrome/sw-toolbox#user-content-toolboxnetworkfirst).
* **skipWaiting** - Allows a simple page refresh to update the app. Defaults to true.

The service worker bootstrap logic will be added to your index.html automatically, using contentFor hooks.

Usage for Broccoli.js
---------------------
Expand All @@ -53,16 +72,16 @@ Upgrade your `index.html` (see below) and you are done.
Options
-------
You can pass some options as the second argument to `writeServiceWorker`:
You can the [options specified above](#configuration) as the second argument to `writeServiceWorker`:
```JavaScript

writeServiceWorker(completeTree, {
serviceWorkerFile: "service-worker.js",
excludePaths: ['tests/', 'online.html',],
includePaths: ['/'],
excludePaths: ['test.*', 'online.html',],
precacheURLs: ['/api/offlineStates'],
fallback: [
'/online.html offline.html'
'/api/states /api/offlineStates'
],
dynamicCache: [
'/api/todos'
Expand All @@ -71,16 +90,6 @@ writeServiceWorker(completeTree, {
});
```
Files can be filtered using regular expressions.
```JavaScript
{
excludePaths: ['index.html', new RegExp(/.\.map$/)],
includePaths: ['']
}
```
Upgrade your index.html
-----------------------
Expand All @@ -98,7 +107,7 @@ If you're not using Ember.js, you can use the following code:
});
} else {
alert('service worker not supported');
}
}
</script>
</html>
```
6 changes: 3 additions & 3 deletions lib/delete-old-caches.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/* global CACHE_PREFIX */
/* global CACHE_VERSION */

self.addEventListener('activate', function(event) {
// Delete all caches handled by broccoli-serviceworker.
logDebug('Deleting out of date caches, current cache version:', CACHE_VERSION);
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.filter(function(cacheName) {
return (cacheName.indexOf(CACHE_PREFIX) === 0 && cacheName !== CACHE_VERSION);
return (cacheName.indexOf('$$$inactive$$$') === -1 && cacheName.indexOf(CACHE_PREFIX) === 0 && cacheName !== CACHE_VERSION);
}).map(function(cacheName) {
logDebug('Deleting out of date cache:', cacheName);
return caches.delete(cacheName);
Expand Down
6 changes: 3 additions & 3 deletions lib/ember-addon.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ module.exports = {

var defaultOptions = {
enabled: this.app.env === 'production',
excludePaths: ['test.*'],
includePaths: ['/'],
excludePaths: ['test.*','robots.txt'],
precacheURLs: []
};

for (var option in defaultOptions) {
Expand All @@ -48,7 +48,7 @@ module.exports = {
treeFor: function() {},

contentFor: function(type, config) {
if (config.environment !== 'test' && type === 'body-footer') {
if (config.environment !== 'test' && (!config.serviceWorker || config.serviceWorker.includeRegistration!== false) && type === 'body-footer') {
return stringifile('registration.js', 'script', __dirname);
}
}
Expand Down
42 changes: 26 additions & 16 deletions lib/fallback-response.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
function getFallbackFromCache(request, values, options) {
logDebug('Fetching from fallback url: '+ options.fallbackURL +'for url: '+request.url);
var req = new Request(options.fallbackURL, request);
return toolbox.cacheFirst(req, values, options).then(function(response) {
if (response) {
logDebug('Got fallback response from cache',response);
return response;
}
});
}

function fallbackResponse(request, values, options) {
logDebug('Looking for fallback for:', request.url);
return toolbox.networkFirst(request, values, options).then(function(response){
logDebug('Default request network got response:', request.url, response);
if (!response) {
logDebug('Fetching from fallback url: '+ options.fallbackURL +'for url: '+request.url);
var req = new Request(options.fallbackURL, request);
var originalResponse = response;
return toolbox.cacheFirst(req, values, options).then(function(response) {
if (response) {
logDebug('Got response from cache',response);
return response;
} else {
return originalResponse;
}
return new Promise(function(resolve, reject) {
toolbox.networkFirst(request, values, options).then(function(response) {
if (response) {
resolve(response);
} else {
logDebug('Network first returned no response, calling fallback from cache.');
getFallbackFromCache(request, values, options).then(resolve).catch(function(err) {
logDebug('Fallback failed with:', err);
});
}
}).catch(function(err){
logDebug('Network first returned err, calling fallback from cache:', err);
getFallbackFromCache(request, values, options).then(resolve).catch(function(err) {
logDebug('Fallback2 failed with:', err);
});
} else {
return response;
}
});
});
}
23 changes: 18 additions & 5 deletions lib/service-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,26 @@ var BroccoliServiceWorker = function BroccoliServiceWorker(inTree, options) {
}
this.inTree = inTree;
options = options || {};
this.skipWaiting = options.skipWaiting || true;
if (options.skipWaiting === false) {
this.skipWaiting = false;
} else {
this.skipWaiting = true;
}
this.debug = options.debug || false;
this.dynamicCache = options.dynamicCache || [];
this.excludePaths = options.excludePaths || ['tests/*'];
this.fallback = options.fallback || [];
this.includePaths = options.includePaths || [];
this.serviceWorkerFile = options.serviceWorkerFile || "service-worker.js";
this.precacheURLs = options.precacheURLs || [];
if (options.includeRegistration === false) {
this.includeRegistration = false;
} else {
this.includeRegistration = true;
}
if (this.includeRegistration === true || !options.serviceWorkerFile) {
this.serviceWorkerFile = "service-worker.js";
} else {
this.serviceWorkerFile = options.serviceWorkerFile;
}
};

BroccoliServiceWorker.prototype = Object.create(brocWriter.prototype);
Expand All @@ -30,7 +43,7 @@ BroccoliServiceWorker.prototype.write = function(readTree, destDir) {
var debug = this.debug;
var dynamicCache = this.dynamicCache;
var fallback = this.fallback;
var includePaths = this.includePaths;
var precacheURLs = this.precacheURLs;
var serviceWorkerFile = this.serviceWorkerFile;
var serviceWorkerTree = funnel(this.inTree, {
exclude: this.excludePaths
Expand All @@ -56,7 +69,7 @@ BroccoliServiceWorker.prototype.write = function(readTree, destDir) {
lines.push(createArrayLine(" '"+file+"'", idx, array.length));
});
lines.push("];");
includePaths.forEach(function (file, idx, array) {
precacheURLs.forEach(function (file, idx, array) {
lines.push("urlsToPrefetch.push('"+file+"');");
});
lines.push("urlsToPrefetch.forEach(function(url) {");
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": "broccoli-serviceworker",
"version": "0.0.4",
"version": "0.0.5",
"description": "A broccoli plugin automating ServiceWorker file creation for Broccoli and Ember.js",
"main": "lib/service-worker.js",
"ember-addon": {
Expand Down

0 comments on commit 12c7847

Please sign in to comment.