Service Worker
Prathik Shetty
THE WEB IS DEAD. LONG LIVE THE INTERNET
- Wired
HTML5 IS DEAD. LONG LIVE HTML5!
- CNET
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046948/iphone_6_plus_.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046962/Screen_Shot_2017-01-23_at_1.19.46_am.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046966/webserver.png)
Web Server
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046966/webserver.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046969/serviceworker.png)
Web Server
Service Worker
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046948/iphone_6_plus_.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046962/Screen_Shot_2017-01-23_at_1.19.46_am.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046966/webserver.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046969/serviceworker.png)
Web Server
Service Worker
Cache
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046948/iphone_6_plus_.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046962/Screen_Shot_2017-01-23_at_1.19.46_am.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4103102/Screen_Shot_2017-09-07_at_11.41.08_am.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046948/iphone_6_plus_.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046962/Screen_Shot_2017-01-23_at_1.19.46_am.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4046969/serviceworker.png)
Service Worker
Push
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4103101/Screen_Shot_2017-09-07_at_11.41.19_am.png)
![](http://i.makeagif.com/media/5-14-2015/-3S6Yz.gif)
A proxy that sits between web applications, and the browser and network
Works only on
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4091240/pasted-from-clipboard-3.png)
Use Cases
Offline Mode
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4095261/1_lm9qERR89v9AbxUI6CXHCQ.png)
Push Notification
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4095264/1_w0paEaD8KZSX4CNBLS6MMw.png)
Background Sync
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4095265/1_u-U6KwWdt07_RNN2pFapQw.png)
& More
- Stub servers for testing
- Manipulate responses
- WebApp Update
- Support for a new image format
- Easy Failover support
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js', {
scope: '/app/'
})
.then(function(registration) {
console.log('SW registered');
});
// .catch a registration error
} else {
console.log('SW registered ');
}
index.html
self.addEventListener('install', function(event) {
// On installation
});
self.addEventListener('activate', function(event) {
// on activation
});
sw.js
Installation
Activate
Error
Idle
Fetch/Push
Terminated
No SW
SW Lifecycle
Event Listeners
- Install
- Activate
- Message
Functional Events
- Fetch
- Sync
- Push
- & more
self.addEventListener('fetch', function(event){
event.respondWith(
caches.match(event.request)
);
});
sw.js
self.addEventListener('sync', function(event) {
if (event.tag === 'my-sync-tag') {
event.waitUntil(doSomething());
}
});
sw.js
self.addEventListener('push', function(event) {
event.waitUntil(
self.registration.showNotification('Notification Yay!!!');
);
});
sw.js
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4047145/Screen_Shot_2017-08-14_at_3.48.22_pm.png)
Examples
var cacheName = 'cache-v1';
var filesToCache = ['/main.js', '/index.html', '/offline.html', ...];
self.addEventListener('install', event => {
event.waitUntil(
caches
.open(cacheName)
.then(cache => {
return cache.addAll(filesToCache);
})
.then(() => {
return self.skipWaiting();
})
);
});
sw.js
Pre-Cache on Install
var cacheName = 'cache-v1';
var filesToCache = ['/main.js', '/index.html', '/offline.html', ...];
var nonImportantFilesToCache = [...];
self.addEventListener('install', event => {
event.waitUntil(
caches
.open(cacheName)
.then(cache => {
cache.addAll(nonImportantFilesToCache);
return cache.addAll(filesToCache);
})
.then(() => {
return self.skipWaiting();
})
);
});
sw.js
Pre-Cache on Install v2
self.addEventListener('fetch', event => {
event.respondWith(
caches
.match(event.request)
.then(response => {
return response || fetch(event.request);
});
);
});
sw.js
Serve from cache on fetch
self.addEventListener('activate',e => {
e.waitUntil(
caches
.keys()
.then(keyList => {
return Promise.all(keyList.map(key => {
if (oldCacheNames.includes(key)) {
return caches.delete(key);
}
}));
});
);
return self.clients.claim();
});
sw.js
Clear old cache on activate
self.addEventListener('fetch',event => {
event.respondWith(
return fetch(event.request)
.then(response => {
cache.put(event.request,response.clone());
return response;
});
);
});
sw.js
Save to cache on fetch
self.addEventListener('fetch',event => {
event.respondWith(
return fetch(event.request)
.catch(function() {
return caches.match(event.request);
});
);
});
sw.js
Fallback to cache
const maxItems = 35;
caches
.open(cacheName)
.then(function(cache) {
cache
.keys()
.then(function(keys) {
if (keys.length < maxItems) {
cache.put(request, response);
} else {
cache
.delete(keys[0])
.then(function() {
cache.put(request, response);
});
}
});
});
sw.js
Limiting Cache
self.addEventListener('notificationclose', function(event) {
var notification = event.notification;
var primaryKey = notification.data.primaryKey;
console.log('Closed notification: ' + primaryKey);
});
sw.js
Closes Push Notification
self.addEventListener('notificationclick', function(event) {
var notification = event.notification;
var primaryKey = notification.data.primaryKey;
var action = event.action;
if (action === 'action1') {
clients.openWindow('https://decanter.com/action1.html?pk='+ primaryKey);
} else {
clients.openWindow('https://decanter.com/view.html?pk='+ primaryKey);
}
});
sw.js
Clicks Push Notification
self.addEventListener('fetch', event => {
event.respondWith(
caches
.match(event.request)
.then(response => {
return response || fetch(event.request);
})
.catch(function() {
if (event.request.headers.get('Accept').indexOf('text/html') !== -1) {
return caches.match('/offline.html');
}
});
);
});
sw.js
Offline
Support
Basic Support
Debugging
Freshness or Performance
Network First or Cache First
Service Workers replaces AppCache
but it's a sledgehammer to crack a nut
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4095184/1_S-JAXSlCqbmYJB0J7WmhZw.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4095212/Screen_Shot_2017-09-04_at_11.25.41_pm.png)
Impact
73/53/100/92
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4101586/Screen_Shot_2017-09-06_at_10.43.06_pm.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4103085/Screenshot_20170907-105322.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4103088/Screenshot_20170907-105633.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4103089/Screenshot_20170907-105519.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4101663/Screen_Shot_2017-09-06_at_10.54.14_pm.png)
First Render
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4101662/Screen_Shot_2017-09-06_at_11.02.08_pm.png)
Repeat View
How to use in Prod
CTRL + C
CTRL + V
<amp-install-serviceworker>
Works great with AMP
![](https://s3.amazonaws.com/media-p.slid.es/uploads/180112/images/4103150/nexus2cee_google-amp-728x400.png)