0

After searching for days for some kind of solution, I have come up empty. My service-worker gets registered, installs, and activates without a problem, but the cache.addAll seems to fail silently.

I am using a controller to serve the service-worker and manifest.json as erb views. I am solely using webpacker and not the asset pipeline, which rules out some of the common gems used for this sort of thing.

Here is my service-worker.js.erb:

const expectedCaches = ['static-v2'];

function onInstall(event) {
    console.log('[Serviceworker]', "Installing!", event);
    event.waitUntil(
    caches.open("static-v2")
        .then(function(cache) {
            return cache.addAll([
                '/offline.html',
                '<%= asset_pack_path 'application.js' %>',
                '<%= asset_pack_path 'media/images/Convertable.png' %>',
                '<%= root_path %>',

            ])
            .then(function(e){ 
                console.log(e);
            })
            .catch(function(e){
                console.log(e.message);
            });
    }).catch(function(err){
        console.log(err.message);
    })
  );
}

function onActivate(event) {
  console.log('[Serviceworker]', "Activating!", event);
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.filter(function(cacheName) {
          // Return true if you want to remove this cache,
          // but remember that caches are shared across
          // the whole origin
          return expectedCaches.includes(cacheName);
        }).map(function(cacheName) {
          return caches.delete(cacheName);
        })
      );
    })
  );
}


function onFetch(event) {
  event.respondWith(
    // try to return untouched request from network first
    fetch(event.request).catch(function() {
      // if it fails, try to return request from the cache
      return caches.match(event.request).then(function(response) {
        if (response) {
          return response;
        }
        // if not found in cache, return default offline content for navigate requests
        if (event.request.mode === 'navigate' ||
          (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
          console.log('[Serviceworker]', "Fetching offline content", event);
          return caches.match('/offline.html');
        }
      })
    })
  );
}

self.addEventListener('install', onInstall);
self.addEventListener('activate', onActivate);
self.addEventListener('fetch', onFetch);

And my manifest.json.erb

{
  "short_name": "My APP",
  "name": "My APP for Everyone!",
  "icons": [
    {
      "src": "<%= asset_pack_path 'media/images/Convertable.png' %>",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "<%= asset_pack_path 'media/images/Convertable.png' %>",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": "<%= root_path %>",
  "background_color": "#fff",
  "display": "standalone",
  "scope": "<%= root_path %>",
  "theme_color": "#000"
}

Like I said, it registers and installs just fine, but when I use chrome dev tools to enter offline mode, it fails to load anything that was supposed to be cached and I get this in the console:

The FetchEvent for "http://localhost:3000/offline.html" resulted in a network error response: an object that was not a Response was passed to respondWith().
Promise.then (async)
onFetch @ service-worker.js:47

which is because undefined is returned as the response since nothing is found in the cache. Debugging into the fetch event handler I find that the CacheStorage object is indeed empty. Looking in the application tab of chrome dev tools I can't find anything caches, although I am not quite sure which cache it should end up in (several are listed).

I get the same result in Firefox as well. I am hoping I missed something simple that someone can point out to me, or at least someone to get me down the right path. I will try to be very responsive to any requests for additional information.

Thank you!

zephos2014
  • 331
  • 1
  • 2
  • 13

1 Answers1

1

Looks like in onActivate event handler you are deleting the items from the Cache Storage which you have added previously in onInstall event.

You should delete the caches which are not in expectedCaches array (now you are doing opposite :-)). So try to change the condition to return !expectedCaches.includes(cacheName); (add exclamation mark), which will filter the old caches only.

  • 1
    *facepalm* ... Thank you so much for being my second pair of eyes when mine have failed me. You really have made my day and I am sorry I took up your time with such a stupid mistake! – zephos2014 Jan 22 '20 at 04:10
  • 1
    You are very welcome! Good luck with your PWA! Thank you! – Dmytro Olefyrenko Jan 22 '20 at 04:13