Service Worker Offline Status

By Ron Royston

July 2018

Table of Contents

Introduction

This article demonstrates using Service Workers to display a customized offline view when the web browser has no network connectivity. Service workers are key to progressive web applications, websites that are installable to the homescreen as an "app".

For a detailed introduction to the Service Workers API see MDN's Service Worker API

Challenges

Several. This is not a feature for beginners to deploy. Support for service workers remains spotty but, if not supported by the browser, the website will function fine. Troubleshooting can be difficult if you do not know how to force a reload on your browser. Custom Offline View In other words, you will think you have deployed an update when in fact the previous service worker remains active.

Finally, since we are effectively inserting a man-in-the-middle between the browser and the network, there are security measures baked in to browsers that generate a variety of misleading errors if our service worker is not implemented precisely correct.

Setup and Installation

Install your service worker, a javascript file, via your websites regular JavaScript. You will want to check for browser support prior to installing the service worker as shown below.

                            
if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
        navigator.serviceWorker.register('/service-worker.js').then(function(registration) {
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
        }, function(err) {
            console.log('ServiceWorker registration failed: ', err);
        });
    });
}
                
            

Service Worker JavaScript Notes

A couple of key features are worth noting. Any file browsed to is automatically added to cache, in addition to the files specified in the array. Updating the CACHE_NAME tells the browser to reevaluate the files cached and deletes extraneous files. Also, we must set the redirect mode of the Request interface of the Fetch API to "manual". Without this adjustment, the custom offline status page will not display.

The Service Worker JavaScript

The script below installs an array of files to the browsers cache. This makes these files available even in case of a network outage. Your array of files may be different. Adjust your script accordingly.

                
var CACHE_NAME = "htt-cache-v007";
var OFFLINE_URL = "/offline";
var REQUIRED_FILES = [
    "/offline",
    "/app.min.css",
    "/app.min.js",
    "/favicons/android-chrome-192x192.png",
    "/favicons/android-chrome-512x512.png",
    "/favicons/apple-touch-icon.png",
    "/favicons/browserconfig.xml",
    "/favicons/favicon-16x16.png",
    "/favicons/favicon-32x32.png",
    "/favicons/favicon.ico",
    "/favicons/manifest.json",
    "/favicons/mstile-150x150.png",
    "/favicons/safari-pinned-tab.svg",
    "/media/logo.png"
];

self.addEventListener('install', function(event) {
    event.waitUntil(caches.open(CACHE_NAME).then(function(cache) {
        return Promise.all(REQUIRED_FILES.map(function(url) {
            return fetch(new Request(url, { redirect: 'manual' })).then(function(res) {
                return cache.put(url, res);
            });
        }));
    }));
});

self.addEventListener('fetch', function(event) {
    if (event.request.mode === 'navigate' || (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
        if(event.request.url.includes("your-domain-name.com")){
            event.respondWith (
                caches.match (event.request, {cacheName: CACHE_NAME}).then(function(resp) {
                    return resp || fetch(event.request).then(function(response) {
                        let responseClone = response.clone();
                        caches.open(CACHE_NAME).then(function(cache) {
                            cache.put(event.request, responseClone);
                        });
                        return response;
                    });
                }).catch(function(error) {
                    return caches.open(CACHE_NAME).then(function (cache) {
                        return cache.match(OFFLINE_URL);
                    });
                })
            );
        }
    }
});

self.addEventListener('activate', function(event) {
    var cacheWhitelist = [CACHE_NAME];
    event.waitUntil(
        caches.keys().then(function(keyList) {
            return Promise.all(keyList.map(function(key) {
                if (cacheWhitelist.indexOf(key) === -1) {
                    console.log('Deleting out of date cache:', CACHE_NAME);
                    return caches.delete(key);
                }
            }));
        })
    );
});
                
            

Troubleshooting

One gotcha that I figured out was how to deal with clean URL's, i.e., URL's where the file extension is removed by the web server. For example, many websites are configured to hide ".html" or ".php" from the URL. The file extension is very important when using service workers. Include files in your service worker as they appear in your website. If your server requires the file extension, then include the file extension in your service worker script. If your server strips the file extension then do not include the file extension in your service worker script.

Remember to test your offline view across browsers. Use developer tools (Ctrl+Shift+i) to assist in monitoring the state of your browsers cache and service worker.

Dialog Title

Cell Phone Number

Your order ID is . The grand total is , or bitcoin.

Delete location?





A password reset link will be emailed to you.




New users register here for an email authenticated account.

Forget your password? Click here to have a new one emailed to you.

Find a bug? Experience an error? How can we do better? We appreciate your feedback.

email
facebook
github
google
twitter

Delete order? This action cannot be undone.

Delete order? This action cannot be undone.