Prathik Shetty
Web Server
Web Server
Service Worker
Web Server
Service Worker
Cache
Service Worker
Push
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
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
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
Network First or Cache First
First Render
Repeat View
<amp-install-serviceworker>
Works great with AMP