Saturday, November 20, 2021

Some pitfalls for using PWA and ServiceWorkers I hoped I knew before

Some pitfalls for using PWA and ServiceWorker I hoped I knew before - So I am writing them here so maybe others will get to rid them before or I can find them again when I'll need them again.

This is not a tutorial for PWA, ServiceWorker. Those are just a few points that I encountered while developing a PWA (Progressive Web App) and ServiceWorker using Vanilla JavaScript and caching mechanism for Offline usage. There are plenty of good PWA ServiceWorker Caching tutorial on the internet.

Full Vanilla JavaScript code is attached all the way at the bottom

Double caches:

First, the cache made by the cache mechanism which you as a coder decide what will be saved in this cache using the cache.addAll() command.

And the second cache is the one the browser automatically caches for example images and javascripts code or others.

Hence might be that when you work offline the browser will return cached images which you did not stated that should be cached only because the browser caching mechanism have cached them.

Cache is empty offline from the website {ignoreVary: true}:

You develop and everything works cool from your localhost server but when deploying and installing on production on your website the offline cache of the serviceworker is empty in the devtools of your Chrome browser. When you work Online you do see the cache.

Now weather I think it appears empty it is a Chrome bug because the cache is there - apparently your code does not recognize the cache using caches.match and tries to request it from the network.

There are two things needed to be done:

  1. Use caches.match(e.request, {ignoreVary: true}) in your code telling the cache match comparing mechanism to ignore the request type and use only the URL itself
  2. When installing the serviceWorker it should be by default working under the same directory it is installed from. Unfortunately it doesn't always work. So when installing the serviceWorker use the scope parameter: navigator.serviceWorker.register('sw1.js', {scope: './'}) 

There can be only one instance of the ServiceWorker for the domain:

So no need to reinstall the worker when you go offline and the list of resources need to be relative to the service worker location:

const includeToCache = [
//  'loader.js?20211118a', // the serviceWorker loader
//  'sw1.js', // the serviceWorker itself

The full code of the serviceWorker

// service worker for PWA loaded from loader.js in pwa.class.php

const cacheName = 'pwa_v10';

const includeToCache = [
//  'loader.js?20211118a',
//  'sw1.js',

// Start the service worker and cache all of the app's content
self.addEventListener('install', e => {
    e.waitUntil( => {
            let c = cache.addAll(includeToCache).catch(err => console.log('SW install addAll FAIL:', err));
            return c;

// Serve cached content when offline
self.addEventListener('fetch', e => {
        caches.match(e.request, {ignoreVary: true}).then(response => {
            return response || fetch(e.request);

// replacing new cache if needed
self.addEventListener('activate', e => {
    // delete any caches that aren’t in cacheName
    // which will get rid of older versions
        caches.keys().then(keys => Promise.all(
   => {
                if(cacheName !== key) {
                    return caches.delete(key);
        }))).then(() => {
            console.log(cacheName + ' now ready to handle fetches!');