This talk aims to introduce the upcoming ServiceWorker technology, its basic functionalities, its lifecycle and its most common use cases. Then it moves to analyse in detail a less obvious implementation of this technology: how to create a wiki engine using ServiceWorker and IndexedDB.
4. Welcome Service Worker!
browser sessions
a-domain.com
a-domain.com
a-domain.com
b-domain.net
c-domain.biz
a-domain.com
sworker.js
the net
some cache
https requests
5. Phase #1: register
Install or update the Service Worker.
navigator.serviceWorker
.register('./worker.js', {scope: './'})
.then(
function(registration){ /* installed */ },
function(){ /* fail! */ }
);
on index.html
6. Phase #2: oninstall, onactivate
Install or update the Service Worker.
oninstall = function(){
/* setup cache, init database */
};
onactivate = function(){
/* clear cache, update database */
};
on worker.js
7. A Service Worker life cycle
a.k.a. why we need activate
index.html UA w.js
w.js (v2)
register install installing
reload
ok installed
activating activate
register install
ok redundant
installing
installed
close activate
ok activating
activated
ok activated
8. Phase #3: fetch
Called on each HTTP request.
onfetch = function(evt){
evt.respondWith(
on worker.js
new Response(new Blob(
['Custom HTML'], {type : 'text/html'}),
{ headers: {"Content-Type": "text/html"}}
));};
9. Using Caches
similar to ES6 Map, still not supported by any browser
oninstall = function(evt){
e.waitUntil(
caches.create("shell-v1").then(
function(cache) {
return cache.addAll(["/app.html"])
}););};
on worker-cache.js
10. Using Caches / 2
onfetch = function(evt){
evt.respondWith(
caches.match(e.request).catch(function() {
return e.default();
}).catch(function() {
return caches.match("/fallback.html");
}));};
on worker-cache.js
11. Using fetch
var youtube = "https://gdata.youtube.com/feeds/api/videos?alt=json";
onfetch = function(evt){
evt.respondWith(
fetch(youtube + '&q=' + evt.request.url.match(/?(.+)$/)[1])
.then(function(res){return res.json();})
.then(function(data){
var imgs = data.feed.entry.map(function(entry){
var url = entry['media$group']['media$thumbnail'][0].url;
return "<img src='" + url + "'>";
}).join("<br>");
return new Response(new Blob([imgs], {type : 'text/html'}), {
headers: {"Content-Type": "text/html"}
});}));};
12. Using IndexedDB
var db;
oninstall = function(evt){
evt.waitUntil(
new Promise(function(resolve){
var request = indexedDB.open('simple-cache');
request.onupgradeneeded = function(){
request.result.createObjectStore('pages',
{keyPath: 'url', autoIncrement: false});
};
request.onsuccess = function(){
db = request.result;
resolve();
};}));};
14. Proof-Of-Concept
A Service Worker powered Wiki Engine
onfetch = function(){
e.respondWith(
new Promise(function(resolve) {
if(//savepage?/.test(e.request.url)){
// - save the page on idDB
// - forge a 'done' response
}else{
// if the page exists on idDB return it
// otherwise forge a form that points to /savepage
}}));};
15. Support? Meh!
But it’s getting better every day.
https://jakearchibald.github.io/isserviceworkerready/