ServiceWorker 
discover the next web game changer
AppCache is bad 
Unable to determinate low connectivity state. 
Local files used even if there is connection.
Remember Shared Web Worker? 
browser sessions 
a-domain.com 
a-domain.com 
a-domain.com 
b-domain.net 
c-domain.biz 
a-domain.com 
swworker.js 
target.postMessage('msg');
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
Phase #1: register 
Install or update the Service Worker. 
navigator.serviceWorker 
.register('./worker.js', {scope: './'}) 
.then( 
function(registration){ /* installed */ }, 
function(){ /* fail! */ } 
); 
on index.html
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
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
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"}} 
));};
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
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
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"} 
});}));};
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(); 
};}));};
onfetch = function(evt){ 
evt.respondWith( 
new Promise(function(resolve){ 
var pageStore = db.transaction('pages').objectStore('pages'); 
pageStore.get(evt.request.url).onsuccess = function(e){ 
if(e.target.result){ 
resolve( 
new Response(new Blob([e.target.result.body], {type : 'text/html'}), { 
headers: {"Content-Type": "text/html"} 
}) 
); 
}else{ 
fetch(evt.request.url).then(function(res){ 
res.text().then(function(text){ 
db.transaction('pages','readwrite').objectStore('pages') 
.add({url: evt.request.url, body: text}) 
.onsuccess = function(){ 
resolve(res); 
};});});}};}));};
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 
}}));};
Support? Meh! 
But it’s getting better every day. 
https://jakearchibald.github.io/isserviceworkerready/
Upcoming features 
push notifications 
geofencing
Thanks! 
@sandropaganotti 
github.com/sandropaganotti/service-worker-wiki

Service worker: discover the next web game changer

  • 1.
    ServiceWorker discover thenext web game changer
  • 2.
    AppCache is bad Unable to determinate low connectivity state. Local files used even if there is connection.
  • 3.
    Remember Shared WebWorker? browser sessions a-domain.com a-domain.com a-domain.com b-domain.net c-domain.biz a-domain.com swworker.js target.postMessage('msg');
  • 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 Workerlife 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 similarto 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 varyoutube = "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 vardb; 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(); };}));};
  • 13.
    onfetch = function(evt){ evt.respondWith( new Promise(function(resolve){ var pageStore = db.transaction('pages').objectStore('pages'); pageStore.get(evt.request.url).onsuccess = function(e){ if(e.target.result){ resolve( new Response(new Blob([e.target.result.body], {type : 'text/html'}), { headers: {"Content-Type": "text/html"} }) ); }else{ fetch(evt.request.url).then(function(res){ res.text().then(function(text){ db.transaction('pages','readwrite').objectStore('pages') .add({url: evt.request.url, body: text}) .onsuccess = function(){ resolve(res); };});});}};}));};
  • 14.
    Proof-Of-Concept A ServiceWorker 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! Butit’s getting better every day. https://jakearchibald.github.io/isserviceworkerready/
  • 16.
    Upcoming features pushnotifications geofencing
  • 17.