Service Workers and Progressive Web Apps - has their time come?

4/14/2020

Currently all major browsers support service workers and PWAs, even iOS Safari. Is it time to take Progressive Web Apps (PWA) more into consideration when building web projects? And what are service workers for anyway?

Here is the current browser support situation when this post was published - check see live here.

image 2

What are they for?

The main goal is to improve the user experience in mobile devices and bridge part of the gap in the user experience between native and web apps. PWAs allow web apps to be more like native apps by offering some of the conveniences of native apps such as offline mode, access to hardware, persistent user permissions, background sync and caching.

What makes a good PWA? Here is a checklist according to Google devs:

Core PWA

  • Starts fast, stays fast
  • Works in any browser
  • Responsive to any screen size
  • Provides a custom offline page
  • Is installable

Optimal PWA

  • Provides an offline experience
  • Is fully accessible
  • Can be discovered through search
  • Works with any input type
  • Provides context for permission requests
  • Follows best practices for healthy code

But what is it really?

Install a web app?

Being a PWA Allows your web app to be installable on mobile devices (save as an app on the home screen of a device for example) if you add a manifest.json.

Here is an example manifest:

{
  "name": "pwa",
  "short_name": "pwa",
  "icons": [
    {
      "src": "/img/icons/android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/img/icons/android-chrome-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "start_url": "/index.html",
  "display": "standalone",
  "background_color": "#000000",
  "theme_color": "#4DBA87"
}

Service workers?

You can create Service Workers - scripts that run in the background that allow your app to work online and offline. They can be used to cache important files for the web application such as

  • Core Javascripts and CSS files
  • Fonts
  • Images
  • HTTP Requests.

Hardware and permissions access

Service Workers give you access to the hardware on the client's device such as camera and bluetooth on a permanent basis - provided the user allows it of course. Capabilities such as Push notifications and background sync also now become possible and persistent until revoked. Click here to see which hardware and permissions are currently accessible to web apps. Having this access closes the gap between web and native apps significantly.

Adding PWA capabilities to a project

I mostly use VueJS on frontend projects and the VUE-CLI provides a simple entry point to build PWAs without additional code.

image 3

Here is what the base code looks like (source) that is provided out-of-the-box in Vue:

workbox.setConfig({
  debug: false,
});

workbox.precaching.precacheAndRoute([]);

workbox.routing.registerRoute(
  /\.(?:png|gif|jpg|jpeg|svg)$/,
  workbox.strategies.staleWhileRevalidate({
    cacheName: 'images',
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 60,
        maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
      }),
    ],
  }),
);

workbox.routing.registerRoute(
  new RegExp('https://some-fancy-api.com'),
  workbox.strategies.networkFirst({
    cacheName: 'api',
  }),
);

workbox.routing.registerRoute(
  new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'),
  workbox.strategies.cacheFirst({
    cacheName: 'googleapis',
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 30,
      }),
    ],
  }),
);

As you can see, it caches images, API requests, remote fonts out of the box. The files are now stored locally on the user device improving the UX without much fuss.

But if you want more than that, here is an example on how to access this functionality from inside a Vue app to tap into some of the hooks and events (offline mode becomes super simple to implement for example):

import { register } from 'register-service-worker';

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    ready() {
      console.log('App is being served from cache by a service worker.\n' +
        'For more details, visit https://goo.gl/AFskqB');
    },
    cached() {
      console.log('Content has been cached for offline use.');
    },
    updated() {
      console.log('New content is available; please refresh.');
    },
    offline() {
      console.log('No internet connection found. App is running in offline mode.');
    },
    error(error) {
      console.error('Error during service worker registration:', error);
    },
  });

In vue.config.js this should also be present:

// vue.config.js
module.exports = {
  PWA: {
    workboxPluginMode: 'InjectManifest',
    workboxOptions: {
        swSrc: 'src/service-worker.js'
    },
    themeColor: '#1da025'
  },
}

Summary

Progressive Web Apps are now well supported in modern browsers and can be used to provide an app-like experience for users. If you work with more complex applications that are frequently used by your users you should definitely look into this technology as it could be used to improve it's daily use as well as unlock new possibilities.

Provided a user install your web app, you can now have an offline mode, do background sync, push notifications to them and have a series of predetermined permissions to access their hardware!