Going offline with

Service Worker

Konrad Dzwinel

Hello!

Brainly.com
Google Developer Expert

Service Worker

Programable proxy

ServiceWorkerPageNetwork

Cache, falling back to network

ServiceWorkerPageCacheNetwork12344

Registration


navigator.serviceWorker.register('/worker.js')
.then( swRegistration => console.log('Success 🎆') ) .catch( err => console.log('Failure 💩', err) );
or (soon):

<head>
  …
  <link rel="serviceworker" href="worker.js" />
  …
</head>
                

URL object


const url = new URL("https://example.com/api/search?query='dfpl'");
if (url.hostname === 'example.com' || url.pathname.includes('/api/') || url.searchParams.has('query')) { //... }

Fetch API


fetch("https://example.com/data.json")
.then(response => { if(response.ok) { // ... } })
.catch(connectionFailed)

const request = new Request("https://example.com/endpoint", {
method: "POST",
headers: customHeaders,
body: '{"conf":"dfpl"}'
}); fetch(request).then(processResponse);

Cache API


caches.open('cache-v1').then(cache => {
cache.put(request, response);
cache.add('/main.js');
cache.addAll(['/main.css', 'https://fonts.com/roboto.woff2']);
cache.match('/main.css').then(cachedResponse => { if (cachedResponse) { showResource(cachedResponse); } });
}).catch(err => console.error(err));

Putting it all together


self.addEventListener('fetch', event => {
const url = new URL(event.request.url); if( url.pathname.startsWith('/article/') ) {
event.respondWith(
cache.match(event.request) .then( cachedItem => { if(cachedItem) return cachedItem;
return fetch(event.request) .then( freshItem => {
cache.put(event.request, freshItem.clone()); return freshItem;
});
});
);
}
});
Brainly.com

Network falling back to cache

ServiceWorkerPageNetworkCache1234
Subject stats

Revalidating caches

ServiceWorkerPageNetworkCache12345
User avatars

Generic fallback

ServiceWorker Page Network Cache 1 2 3 4 5
  • fetch different image based on network capabilities
  • cache content when user requests it
  • render templates on-the-fly
  • transpile code on-the-fly
  • mock responses while developing

Background sync

Saving your message
Page Sync Service Worker Network 1 2 3

Registration


navigator.serviceWorker.ready.then(swRegistration => {
  swRegistration.sync.register('mySync');
});

Event


self.addEventListener('sync', event => {
  if (event.tag == 'mySync') {
    event.waitUntil(doSomeStuff());
  }
});

Push

Subscription


navigator.serviceWorker.register('/worker.js').then(swRegistration => {
swRegistration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: publicKey }).then( sub => console.log('endpoint:', sub.endpoint) );
});
PushMessageServiceWorkerNetworkNotificationCache1234

Handling requests


self.addEventListener('push', event => {
event.waitUntil( self.registration.showNotification('Title', { body: 'The Message', icon: 'images/icon.png', tag: 'my-tag' }));
});

DevTools

DevTools Application SW tab DevTools Application Cache tab DevTools Sources SW tab DevTools Console SW tab
ServiceWorker enthusiasm
Is ServiceWorker ready?

Thank you!

@kdzwinel