A pluggable approach to Service Workers for Ember.js
Please test this addon on your local/staging environment before deploying to production. Please report any errors or odd behaviour when testing!
Without any extra addons all this addon does is install a Service Worker, but the Service Worker itself will do nothing. This allows you to craft a set of addons that make the Service Worker function the way you want it to.
ember install ember-service-worker
- ember-service-worker-asset-cache
- ember-service-worker-cache-first
- ember-service-worker-cache-fallback
For a full list of available Ember Service Worker plugins: click here
To create an Ember Service Worker plugin, you first need to add the
ember-service-worker-plugin
keyword to the keywords
option in the plugin's
package.json
From within a service worker plugin, you can modify the contents of the generated service worker
(built to dist/sw.js
) and/or you can modify the mechanism of service worker registration ( built
to dist/sw-registration.js
).
Create a service-worker/index.js
file within in the root of your addon. This file will
automatically be loaded by the created service worker.
Other files in the service-worker
file are available for import
via standard ES6 module
semantics.
To make addons simple and pluggable, some middleware has been added.
If you want to listen for fetch
in your addon, you will need to register this
through the addFetchListener
function. This expects a callback function which
receives the event as argument, just as the callback to
addEventListener('fetch', ...)
does. The callback can return a
Promise that resolves to a response or it can return undefined
. If the response is undefined
the next fetch
handler that has been registered will be called, otherwise the
response from the promise will be used and no further fetch
handlers will be
called.
Example:
import { addFetchListener } from 'ember-service-worker/service-worker';
addFetchListener(function() {
// special sauce here
});
This is a constant that you can utilize which is updated for every build of the service worker. You could use this as part of the cache key:
import { VERSION } from 'ember-service-worker/service-worker';
var CACHE_NAME = 'asset-cache-' + VERSION;
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
// more stuff here
})
);
});
This is a constant that you can utilize which is tied to the project (and all levels of dependencies). One use case for this, is to ensure that the service worker in use is paired with the correct project:
import { PROJECT_REVISION } from 'ember-service-worker/service-worker';
self.addEventListener('message', function(event) {
if (event.data && event.data.command === 'verify-project-revision') {
if (PROJECT_REVISION !== event.data.PROJECT_REVISION) {
// handle when the project revision doesn't match
}
}
});
Create a service-worker-registration/index.js
file within the root of your addon. This file
is required to register the service worker (and its scope).
Other files in the service-worker-registration
file are available for import
via standard
ES6 module semantics.
You can use this method to register a callback to execute after registration is successful.
The callback will be passed the registration
object.
Example:
import { addSuccessHandler } from 'ember-service-worker/service-worker-registration';
addSuccessHandler(function(reg) {
// do stuff on successful registration
});
You can use this method to register a callback to execute if registration has errored.
The callback will be passed the registration
object.
Example:
import { addErrorHandler } from 'ember-service-worker/service-worker-registration';
addErrorHandler(function(reg) {
// do stuff on errored registration
});
This is a constant that you can utilize which is tied to the project (and all levels of dependencies). One use case for this, is to ensure that the service worker in use is paired with the correct project:
import { addSuccessHandler, PROJECT_REVISION } from 'ember-service-worker/service-worker-registration';
addSuccessHandler(function(reg) {
return navigator.serviceWorker.ready
.then(function() {
navigator.serviceWorker.controller.postMessage({
command: 'verify-project-revision',
revision: PROJECT_REVISION
});
});
});
It is also possible to add service worker code to your app directly. To do this
add a service-worker/index.js
or service-worker-registration/index.js
file to
your project.
This works exactly as authoring plugins.
This library follows Semantic Versioning
Please do! We are always looking to improve this library. Please see our Contribution Guidelines on how to properly submit issues and pull requests.
DockYard, Inc. © 2016