Making PWAs work offline with Service workers

Service Workers are a virtual proxy between the browser and the network. They finally fix issues that front-end developers have struggled with for years — most notably how to properly cache the assets of a website and make them available when the user’s device is offline.

Security

Offline First

“Progressive” in PWA

Service workers in the js13kPWA app

Registering the Service Worker

if('serviceWorker' in navigator) {
navigator.serviceWorker.register('./pwa-examples/js13kpwa/sw.js');
};

Lifecycle of a Service Worker

Installation

self.addEventListener('install', (e) => {
console.log('[Service Worker] Install');
});
var cacheName = 'js13kPWA-v1';
var appShellFiles = [
'/pwa-examples/js13kpwa/',
'/pwa-examples/js13kpwa/index.html',
'/pwa-examples/js13kpwa/app.js',
'/pwa-examples/js13kpwa/style.css',
'/pwa-examples/js13kpwa/fonts/graduate.eot',
'/pwa-examples/js13kpwa/fonts/graduate.ttf',
'/pwa-examples/js13kpwa/fonts/graduate.woff',
'/pwa-examples/js13kpwa/favicon.ico',
'/pwa-examples/js13kpwa/img/js13kgames.png',
'/pwa-examples/js13kpwa/img/bg.png',
'/pwa-examples/js13kpwa/icons/icon-32.png',
'/pwa-examples/js13kpwa/icons/icon-64.png',
'/pwa-examples/js13kpwa/icons/icon-96.png',
'/pwa-examples/js13kpwa/icons/icon-128.png',
'/pwa-examples/js13kpwa/icons/icon-168.png',
'/pwa-examples/js13kpwa/icons/icon-192.png',
'/pwa-examples/js13kpwa/icons/icon-256.png',
'/pwa-examples/js13kpwa/icons/icon-512.png'
];
var gamesImages = [];
for(var i=0; i<games.length; i++) {
gamesImages.push('data/img/'+games[i].slug+'.jpg');
}
var contentToCache = appShellFiles.concat(gamesImages);
self.addEventListener('install', (e) => {
console.log('[Service Worker] Install');
e.waitUntil(
caches.open(cacheName).then((cache) => {
console.log('[Service Worker] Caching all: app shell and content');
return cache.addAll(contentToCache);
})
);
});

Activation

Responding to fetches

self.addEventListener('fetch', (e) => {
console.log('[Service Worker] Fetched resource '+e.request.url);
});
self.addEventListener('fetch', (e) => {
e.respondWith(
caches.match(e.request).then((r) => {
console.log('[Service Worker] Fetching resource: '+e.request.url);
return r || fetch(e.request).then((response) => {
return caches.open(cacheName).then((cache) => {
console.log('[Service Worker] Caching new resource: '+e.request.url);
cache.put(e.request, response.clone());
return response;
});
});
})
);
});

Updates

var cacheName = 'js13kPWA-v1';
contentToCache.push('/pwa-examples/js13kpwa/icons/icon-32.png');// ...self.addEventListener('install', (e) => {
e.waitUntil(
caches.open('js13kPWA-v2').then((cache) => {
return cache.addAll(contentToCache);
})
);
});

Clearing the cache

self.addEventListener('activate', (e) => {
e.waitUntil(
caches.keys().then((keyList) => {
return Promise.all(keyList.map((key) => {
if(key !== cacheName) {
return caches.delete(key);
}
}));
})
);
});

Other use cases

Summary

Software Developer