I've built a service for websites to easily integrate push notifications into their site but the current Chrome implementation also requires they set up a manifest and service worker.
Is there any way to set up the service worker and manifest with only a single line of Javascript?
Yes you can reduce the steps to getting them to host a service worker file on their origin and include a single line of Javascript in their page.
You can do it by using the Javascript they include to:
Your Javascript should look something like this:
navigator.serviceWorker.register('sw.js').then(function(registration) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
var head = document.head;
var noManifest = true;
// Walk through the head to check if a manifest already exists
for (var i = 0; i < head.childNodes.length; i++) {
if (head.childNodes[i].rel === 'manifest') {
noManifest = false;
break;
}
}
// If there is no manifest already, add one.
if (noManifest) {
var manifest = document.createElement('link');
manifest.rel = 'manifest';
manifest.href = 'manifest.json';
document.head.appendChild(manifest);
}
});
Note how I've avoided adding a manifest tag if one already exists.
Your service worker should look something like:
self.addEventListener('fetch', function(e) {
if (e.request.context === 'manifest') {
e.respondWith(new Promise(function(resolve, reject) {
fetch(e.request).then(function(response) {
if (response.ok) {
// We found a real manifest, so we should just add our custom field
response.json().then(function(json) {
json.custom_field = 'Hello world';
var blob = new Blob([JSON.stringify(json)], { type: 'application/json' });
console.log('Appended a custom field to the pre-existing manifest');
resolve(new Response(blob));
});
} else {
// There was no manifest so return ours
console.log('Injected a custom manifest');
resolve(new Response('{ "custom_field": "Hello world" }'));
}
});
}));
}
});
// These pieces cause the service worker to claim the client immediately when it is registered instead of waiting until the next load. This means this approach can work immediately when the user lands on your site.
if (typeof self.skipWaiting === 'function') {
console.log('self.skipWaiting() is supported.');
self.addEventListener('install', function(e) {
// See https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-global-scope-skipwaiting
e.waitUntil(self.skipWaiting());
});
} else {
console.log('self.skipWaiting() is not supported.');
}
if (self.clients && (typeof self.clients.claim === 'function')) {
console.log('self.clients.claim() is supported.');
self.addEventListener('activate', function(e) {
// See https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#clients-claim-method
e.waitUntil(self.clients.claim());
});
} else {
console.log('self.clients.claim() is not supported.');
}
Note how it only intercepts requests for manifests, and checks if one actually exists. If it does, the service worker simply appends our custom fields to it. If the manifest doesn't already exist we return our custom field as the whole manifest.
Update (August 25th 2015): I just read that Request.context has been deprecated so unfortunately you will need to find a new way of discovering whether a request is for a manifest or something else in place of the line if (e.request.context === 'manifest')
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With