PWAs 2019 | Service Worker Cookbook (@GitHub)

Make Installable :: Web App Manifest (JSON) | w3.org

<!-- Startup configuration -->
<link rel="manifest" href="manifest.webmanifest">

<!-- Fallback application metadata for legacy browsers -->
<meta name="application-name" content="AppNameShort">
<link rel="icon" sizes="16x16 32x32 48x48" href="lo_def.ico">
<link rel="icon" sizes="512x512" href="hi_def.png">

App Shell Model

Service Worker API

Service worker lifecycle

To make sure service workers don’t break websites, they go through a strictly defined lifecycle. This makes sure that there is only one service worker controlling your website (and therefore only one version of your site exists).

1. Register :: navigator.serviceWorker.register

2. Install :: CacheStorage Interface

If anything goes wrong during this phase, the promise returned from navigator.serviceWorker.register (@ app.js) is rejected.

Force Activation upon Install :: self.skipWaiting()

self.addEventListener('install', (event) => {
    event.waitUntil(/* ... */)
        .then(() => self.skipWaiting())

3. Activate :: waitUntil()

When you successfully install the new service worker, the activate event will be fired. The service worker is now ready to control your website –– but it won’t control it yet. The service worker will only control your website when you refresh the page after it’s activated. Again, this is to assure that nothing is broken.

The window(s) of a website that a service worker controls are called its clients. Inside the event handler for the install event, it’s possible to take control of uncontrolled clients by calling self.clients.claim().

self.addEventListener('activate', e => self.clients.claim())

Intercepting Requests :: per Strategy | @ WorkBox

self.addEventListener('fetch', (event) => {
    event.respondWith( 
        caches.match(event.request)
            .then((response) => {
                // Per STRATEGY: Network First, Cache Falling Back to Network, ...  

Save/Cache POST @ offline

BackgroundSynch API (Not well supported)

self.addEventListener('sync', (event) => {
    if (event.tag === 'syncAttendees') {
        event.waitUntil(doSynch())
    }
})

… a sync event will be emitted when the system decides to trigger a synchronization. This decision is based on various parameters: connectivity, battery status, power source, etc. ; so we can not be sure when synchronization will be triggered.

Add to Home Screen :: beforeinstallprompt event (@ Chrome)

window.addEventListener('beforeinstallprompt', (e) => {
    // Stash the event so it can be triggered later.
    deferredPrompt = e
    // Update UI notify the user they can add to home screen
    showInstallPromotion()
})

WorkBox

Other