Service Workers

Go Offline or Go Home

👷

Hi! I'm Steve Gherkin

Pickle with 4 years of experience in condiments.

Work at Brinelify.

Expert in juice network solutions.

Yves Gurcan

Full Stack Developer
at CBT Nuggets

yvesgurcan

Have you ever used
service workers?

Yes, at work.
Yes, on a personal project.
No, but I heard about them.
No, and I don’t know what they are.

How many websites will stay reactive while users are disconnected?

State of JavaScript 2018: Which new browser APIs are gaining traction?

🔥🔥🔥 Hot stuff! 🔥🔥🔥

Can I Use: Service workers are supported by pretty much all browsers

The buzz word: PWA

What makes a website a Progressive Web App?

The Google checklist

1. App served over HTTPS (required for service workers anyway).

2. Responsive design.

3. Accessible offline.

4. App manifest.

5. Time to interactive <10 seconds on first visit in 3G.

6. Cross-browser compatibility.

7. Show something when clicking on a link (loading indicator or skeleton).

8. Unique URLs for each page.

The benefits of service workers

Offer an offline experience to your users.

Increase performances by caching anything you want in the browser.

Pay less by decreasing the load on your servers.

Send notifications remotely to the browser.

How does a worker work?

It just takes a few lines

// index.js
navigator.serviceWorker.register('serviceWorker.js')
    .then(registration => console.log('Service worker registered.'))
    .catch(error => console.error('Service worker could not register.'));
// serviceWorker.js
const addUrlsToCache = async (urls) => {
    const cache = await caches.open('my-cache')
    return await cache.addAll(urls);
}

const handleFetchRequest = async (event) => {
    const result = await caches.match(event.request)
    if (result) {
        return result;
    }

    return fetch(event.request);
}

self.addEventListener('install', event => {
    return event.waitUntil(addUrlsToCache(['/', '/style.css', '/index.js']))
});

self.addEventListener('fetch', event => {
    event.respondWith(handleFetchRequest(event));
});

Google to the rescue (again)

Workbox with Wepack

// webpack.config.js

const { GenerateSW } = require('workbox-webpack-plugin');

module.exports = () => ({
    plugins: [
        new GenerateSW({
            swDest: 'workboxServiceWorker.js',
            maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
            clientsClaim: true,
        })
    ]
});

Simple configuration.

Customizable.

Generates a service worker at compilation.

Better than a mobile app

Gotchas

The notion of scope in service workers can be confusing.

Since service workers live on the client, you're not fully in control when to update the script.

The nature of the beast makes debugging more difficult.

One service worker to rule them all

However, from personal experience, you're better off with a single service worker in control of your whole app.

// index.js
navigator.serviceWorker.register('/assetsServiceWorker.js', { scope: '/assets' })

You can restrict which requests a service worker intercepts (such as requests under the /assets scope, for example).

Service worker lifecycle

Start:        myServiceWorker.register()

Install:      Service worker creates pre-cache.

Wait:         Skipped if there is not an active service
                   worker yet.
                   Prepares to take over old service worker.

Activate:  Serves cache or fetches data.
                   Additionally, creates cache dynamically.

Stop:         myServiceWorker.unregister()

Updating your worker:
A delicate matter

Your service worker will update as expected if your app is not open on your user's browser.

Otherwise, your updated service worker will not activate. As a consequence, your users might get stuck with an old service worker forever!

You can circumvent this behavior by calling self.skipWaiting() in the worker script.

Updating your worker

The brutal way: Desync app from service worker

  • If you call skipWaiting() without refreshing the app, it might try to access deleted cache and all hell might break loose.

The gentle way: A new beginning

  • Prompt user to reload the app after calling skipWaiting().

  • If they agree, it will let the new worker take over.

  • If they don't, the new worker will take control when they close the tab anyway.

Prompting for updates

// index.js
async updateServiceWorker(registration) {
    // trigger update check manually
    const updatedRegistration = await registration.update();
    updatedRegistration.addEventListener('updatefound', () => {
        // the state of the installing SW has changed
        updatedRegistration.installing.addEventListener('statechange', (event) => {
            // new SW is ready for activation
            if (event.target.state === 'installed') {
                promptUserToRefreshApp(updatedRegistration);
            }
        });
    });

    if (updatedRegistration.waiting) {
        promptUserToRefreshApp(updatedRegistration);
    }
}

promptUserToRefreshApp(registration) {
    if (window.confirm('A new version of the app is available. Reload the app?')) {
        activateUpdatedServiceWorker(registration);
        window.location.reload()
    }
}

activateUpdatedServiceWorker = (registration) => {
    registration.waiting.postMessage({ type: 'SKIP_WAITING' });
}

Debugging with
Chrome DevTools

Debugging with
Chrome DevTools

Keep control of your service workers while developing them.

Familiarize yourself with the lifecycle of your service workers.

See which version of a service worker is running.

Test offline functionalities.

Nuke a bad service worker.

Resources

ServiceWorker Cookbook: https://serviceworke.rs

Slides: github.com/eugenewebdevs/archive/tree/master/2019-06-27-Service-Workers

State of JavaScript 2018: 2018.stateofjs.com

Can I Use Service Workers: caniuse.com/#search=service%20workers

Is Service Worker Ready? jakearchibald.github.io/isserviceworkerready

The ServiceWorker is coming, look busy: youtube.com/watch?v=SmZ9XcTpMS4

ServiceWorkers Outbreak: youtube.com/watch?v=CPP9ew4Co0M

Keep in touch!

yvesgurcan

Service Workers: Go Offline or Go Home

By Yves Gurcan

Service Workers: Go Offline or Go Home

Link to the Meetup event: https://www.meetup.com/eugenewebdevs/events/261941044/. Yves explores what service workers are and how to implement them in your applications. The talk includes use cases, details on the benefits and caveats of using service workers, and info on Workbox (a Google library to facilitate the usage of workers). We also explore the Cache API and how you can create an experience close to (or even better than) native mobile apps with progressive web applications.

  • 99
Loading comments...

More from Yves Gurcan