Service workers
Published: 2021-06-10 17:43:39

A service worker is a script that your browser runs in the background, separate from a web page, opening the door to features that don't need a web page or user interaction. This includes things like push notifications and background sync.

Note: Service workers are currently only supported in Chrome, Firefox Nightly, and Opera.

The Problem

When you're offline, you don't have access to your server. This means that if you try to send a push notification to a user while they're offline, it won't work. If you try to send an email while they're offline, it won't work. If you try to save a draft of a new message, it won't work.

Even worse, your service worker can't tell the difference between "the user is offline" and "the network is down". It's all the same to the service worker. So if you try to save a draft of a new message while the network is down, it won't work either. You'll end up with two drafts saved on your device: one that's never been sent, and one that's been sent but never delivered.

The Solution

Service workers give us the ability to respond to network conditions using the Offline API. When we detect that the user is offline, we can tell the service worker not to try to do anything that requires a network connection. In this case, that means saving drafts of new messages when we detect that the user is offline.

This also means that we can send push notifications and emails even when the user is offline! And even better: if we detect that the network is down, we can tell the service worker not to try sending any messages at all. We don't want our users to get frustrated by seeing drafts of messages they've already received!

In practice, this looks like this:

The code for detecting if the user is online or offline looks like this:

```
if (navigator.onLine) { 
   // show "online" indicator 
} else { 
   // show "offline" indicator 
} 
if ( navigator.onLine ) { 
   // show "online" indicator 
} 
else { 
   // show "offline" indicator 
}
```

As an added bonus, you can also check navigator.onLine for error conditions: 
```
if (navigator.onLine && navigator.onLine.error) { 
   // show error message 
} 

if (navigator.onLine && navigator.onLine.error ) { 
   // show error message 
}
```

You can use these values in your service worker script as well: 
```
if (navigator.onLine) { 
   // show "online" indicator 
} else { 
   // show "offline" indicator 
}
if (navigator.onLine) { 
   // show "online" indicator 
} else { 
   // show "offline" indicator 
} 
```

Then in your service worker script, you can respond accordingly: 
```
self.addEventListener('fetch', function(event) { 
   var request = event.request; 
   var response = event.response; 
   var type = event.type; 
   switch(type) { 
      case 'fetch': // Note: fetch events don't always have 
         // responses, so check for both fetch and response 
         break; 
      case 'response': // Only do something if it's an HTTP 
         response if (response) { 
            var url = response.url; 
            console.log('Response from ' + url);  
         } 
         break; 
      case 'fetch': // Only do something if it's an HTTP 
         // fetch 
          if (request) {  
             console.log('Request for ' + request); 
             request = null; 
          } 
          break; 
      default: break; 
      } 
   });
```