Experiment with PWA and Service Workers

Just toying around with a simplified app to explore the very very basics of modern Progressive Web Apps and Service Workers

up

2019-04-16

Quite a simple experiment, actually. Decided to reduce the problem down to only what I could write and develop with a text editor – IE no frameworks or tools outside of what the browser provides.

The app I made is called GoGoJuice, the source of which can be found on GitHub.

It’s little more than following a tutorial on service workers and PWA’s, but it’s a useful little thing.

Making the app a Progressive Web App is really about 2 things:

  1. a manifest file
  2. a service worker

There are nuances for them, but GoGoJuice eschews almost everything in order to just get to the core of it. Below is everything, minus the icons (full version):

{
    "name": "Automotive Go-Go Juice Tracker",
    "short_name": "GoGoJuice",
    "description": "Track your automotive go-go juice usage.",
    "icons": [
    ],
    "start_url": "/index.html",
    "display": "fullscreen",
    "theme_color": "#B12A34",
    "background_color": "#B12A34"
}

Doesn’t matter what the file is called, really. Just needs to be referenced in your index file, IE this needs to be in the <head> section:

<link rel="manifest" href="gogojuice.webmanifest">

This sets up all the info that a platform needs to know in order to facilitate your app, but it does not yet cache your app so that it can be used offline. Right now it is an online-only app.

Which is where service workers come in! They are reactive bits of code that can cache request/response objects – IE files that your app requires to be useful offline. I’d read the MDN Article for a lot more detail than I can provide.

Ultimately, the worker is registered in your js somewhere:

if('serviceWorker' in navigator) {
   navigator.serviceWorker.register('/sw.js');
}

And then you have a js file (in the case of GoGoJuice, sw.js) that registers callbacks for events and handles whatever needs to be done, like caching files.

GoGoJuice, specifically, doesn’t require that much. Really just the index.html, style.css, app.js, and icons need to be cached, and then it’s good to go:

var cachename = 'gogojuice-1';
var appshellfiles = [
  '/',
  '/index.html',
  '/style.css',
  '/app.js',
  '/favicon.ico',
  '/icons/icon-32.png',
  '/icons/icon-64.png',
  '/icons/icon-96.png',
  '/icons/icon-128.png',
  '/icons/icon-168.png',
  '/icons/icon-192.png',
  '/icons/icon-256.png',
  '/icons/icon-512.png',
  '/icons/settings-32.png',
];

self.addEventListener('install', function(e) {
  console.log('[sw] install');
  e.waitUntil(
    caches.open(cachename).then(function(cache) {
      console.log('[sw] caching all');
      return cache.addAll(appshellfiles);
    })
  );
});

self.addEventListener('fetch', function(e) {
  e.respondWith(
    caches.match(e.request).then(function(r) {
      console.log('[sw] fetching: '+e.request.url);
      return r || fetch(e.request).then(function(response) {
        return caches.open(cacheName).then(function(cache) {
          console.log('[sw] caching new: '+e.request.url);
          cache.put(e.request, response.clone());
          return response;
        });
      });
    })
  );
});

Super simple, when you cut down to the core of it.