Why my Service Worker is always waiting to activate?

Victor Ferreira picture Victor Ferreira · Feb 19, 2018 · Viewed 13.3k times · Source

I have this very basic question

I'm striving to understand the Service Worker life cycle, or even better, what in practical terms initialize and change the states.

I got 2 questions right now:

1 - in chrome://inspect/#service-workers there are always 2 ou 3 lines, showing service workers all running with the same PID. Why? Why not only one?

2- When i inspect my service worker on refresh i got this:

  • #566 activated and is running [stop]
  • #570 waiting to activate [skipWaiting]

What does that mean? What is 566 and what is 570? I suppose they are instances of the the sw, but why there are two of them? And why 570 is still waiting? What do I have to do to make sure it will be registered-installed-activated?

3- General questions

  • What ends the install event in a normal life cycle?
  • What fires the activate event in a normal life cycle?

index.html

<script>
  if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
      navigator.serviceWorker.register('./sw.js')
      .then(function(registration) {
        // successful
        console.log('Success: ', registration);
      }).catch(function(err) {
        // registration failed
        console.log('Error: ', err);
      });
    });
  }
  </script>

sw.js

var cache_name = 'v1';

var cache_files = [
  './',
  './index.html',
  './style.css'
]

self.addEventListener('install', function(e){
  console.log('SW install:', e);
  e.waitUntil(
    caches.open(cache_name)
    .then(function(cache){
      console.log('cache', cache);
      return cache.addAll(cache_files);
    })
    .then(function(cache){
      console.log('Cache completed');
    })
  )
});

self.addEventListener('activate', function(event) {
  console.log('SW activate:', event);
});

self.addEventListener('fetch', function(e){
  console.log('SW fetch:', e.request.url)

  e.respondWith(
    caches.match(e.request)
    .then(function(cache_response){
      if(cache_response) return cache_response;

      return fetch(e.request);
    })
    .catch(function(err){
      console.log('Cache error', err)
    })
  );
});

Thanks!

Answer

pate picture pate · Feb 19, 2018

The ids shown by Chrome Devtools are internal. Just to point out. So they name all the Service Workers by an id. That's all.

The reason for having two SWs at the "same time" is that you had one, then you reloaded the page, navigated away and came back, or something along those lines, and you got another one. But at this point in time, when you "just got another one", it has yet to be activated and the previous SW is still controlling the page. The new SW will take control over the previous SW when you navigate back to the site from somewhere else, refreshing the page isn't enough. Basically this means closing all tabs and windows of the page and then loading it again, then the new SW takes over.

The time when the new SW hasn't taken over is called waiting state which happens between installation and activation. That can be skipped by calling self.skipWaiting() from inside the install handler of the SW.

The basic idea behind this flow is the page shouldn't be controlled by a SW that didn't control the page when the page was loaded – for this reason the first visit to a site that registers an SW will not be controlled by that SW, only the second time the SW will be activated etc.

You should REALLY read this brilliant article: The Service Worker Lifecycle