2

I have a fairly simple service worker (see code below), with which I run into the following problem:

On each refresh the browser tries to install a new service worker (even though there are no changes in the service worker nor my cached resources). This gets my service worker blocked in a constant "installing" phase after a first refresh of my site (see Screenshot). This happens independently, if I use skipWaiting() or not.

Everything else looks fine: No error messages on registration, all resources can be found in "Cache Storage" etc.

EDIT: So I have found that a call of history.pushState() on initialization of our app is blocking my service worker in "installing" state. If I run the app without this call or with a setTimeout(), the service worker runs fine. This gives me the impression that a call of history.pushState() BEFORE service worker registration makes the worker block. Any ideas why?

var version = 1489760334594;
var CACHE_NAME = 'mini-cache-v' + version;

var urlsToCache = ['./index.html','./app.css','./app.js','./assets/layers-2x.png','./assets/layers.png','./assets/logo-x48.png','./assets/logo.png','./assets/marker-icon.png','./assets/marker-shadow.png','./assets/poi.png','./assets/status.png','./assets/MaterialIcons-Regular.eot','./assets/MaterialIcons-Regular.ttf','./assets/roboto-regular.ttf','./assets/MaterialIcons-Regular.woff','./assets/MaterialIcons-Regular.woff2'];


self.addEventListener('install', function (event) {
  console.log('INSTALL SW: ', CACHE_NAME);
  //Open cache and add new resources from network
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function (cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache)
          .then(function(){
            console.log('Added resources');        
          })
      })  
  );
  //Activate new SW directly
  // console.log('SKIP WAITING');
  // return self.skipWaiting();
});

self.addEventListener('activate', function(event) {
  console.log('ACTIVATE SW: ', CACHE_NAME);
  //Delete old caches
  event.waitUntil(
    caches.keys().then(function(keyList) {
      return Promise.all(keyList.map(function(key) {
        if (key !== CACHE_NAME) {
          return caches.delete(key);
        }
      }));
    }) 
  );
});

self.addEventListener('fetch', function(event) {
  //If present serve from cache, else from network
  event.respondWith(
    caches.open(CACHE_NAME).then(function(cache){
      return cache.match(event.request.url)
        .then(function(response) {
          if (response) {
            console.log('SERVED FROM CACHE:', response);
            return response;
          }
          return fetch(event.request).then(function(response){
              // console.log('Response from network is:', response);
              return response;
          });
        }
      )
    })
  );
});
tobik
  • 1,129
  • 1
  • 8
  • 9
  • Rather simple question, but does the cache get deleted? – Nemanja Milosavljevic Mar 17 '17 at 21:51
  • While the service worker is blocked in the "installing" phase the cache does not get deleted. When I do a change in the sw and the new one gets registered the cache gets deleted and the new cache gets inserted as expected. However, to get the new sw registered I need to close/open chrome twice. Once to dissolve the blocked "installing" state and once to get the new sw activated (skipWaiting). Ps: I just edited the post adding observations I made today regarding localStorage (see above). – tobik Mar 20 '17 at 13:14
  • So I have found what is blocking my service worker in "installing" state. It is a call of history.pushState() on initialization of our app. If I run the app without this call, the service worker runs fine. However I would like to understand why a call of history.pushState() in our app code conflicts with the service worker. Any ideas? – tobik Mar 21 '17 at 13:15
  • From what I know so far, local storage and service workers do not play nicely together because one is synchronous and other one is asynchronous. Just from taking a look at your code, I'd suggest checking your "fetch" event for the `cache.match` method. I'm not sure if you should be checking for the `event.request.url` or just `event.request`. You can try making it so that the service worker gets updated on reload in "Applications > Service Workers" tab in chrome dev toolbar, then hard reload will help you debugging by avoiding the browser close/open process. Or remove it manually. – Nemanja Milosavljevic Mar 21 '17 at 14:30
  • Yes indeed `code`cache.match(event.request.url) is a workaround instead of using `code`cache.match(event.request). The latter somehow returns undefined in my server setup: http://stackoverflow.com/questions/42813582/service-worker-cache-matchrequest-returns-undefined – tobik Mar 22 '17 at 11:21

0 Answers0