Signup/Sign In
LAST UPDATED: NOVEMBER 17, 2022

Write your first Service Worker - Simplest Guide

    If you want to enhance the experience that your web application is delivering to its users, and you are thinking of going the PWA or Progressive Web Application way, then this tutorial (step by step guide) is for you.

    Progressive Web Application is not a specially developed web application, rather it's a web application that follows some best practices, and utilizes the native Web APIs to deliver a seamless experience to its users.

    As per Google, a web application should have F.I.R.E to become a PWA. LOL! Joking. FIRE here stands for Fast, Installable, Reliable, and Engaging.

    So how do you get this F.I.R.E, well there are a couple of things that you must do, one of them is utilizing Service Worker, to cache important resources of your website, and to deliver an Offline experience to your users.

    In this tutorial, we will learn, what is a Service Worker? how to set up a basic Service Worker for your web application and how you can use it to cache static resources and make your web application fast.

    What is Service Worker?

    A service worker is a JS script that lies between the browsers and the internet.

    When a client enters a URL in the browser, and hits enter, then what happens? Well, the domain name entered in the URL is resolved, the IP address for the server is looked up and the request is sent to the server for response.

    If, the website has implemented Service Worker, then when the website is visited the first time, the browser will download the serviceworker.js (or sw.js) file and start the service worker in the browser for that website.

    The next time, when you will open the same website, then the service worker running on the browser will intercept the request first, and will then simply forward it to the server.

    Now, you can do some pre-processing on the request in the service worker. You can also stop the request from being sent to the server. Yes! service worker can intercept the request, give the response back, and never send the request to the server.

    It's a dangerous weapon, hence must be used carefully.

    Service Worker is nothing but a JS file, overriding a few methods to manage the HTTP request. We can configure Service Worker to download and store some response in cache to be used later.

    Service Worker Lifecycle

    A service worker is installed when your website's page is opened and after installation, it is activated. Only after successful activation, it will become functional.

    Once it is active and running, then it can intercept the HTTP requests and manage them.

    In simple words, the first-page load will not have a Service worker serving the request. When a user visits your website for the first time the service worker is installed and activated, then from consecutive visits, the service worker will come into the picture.

    If you are caching any static resource or a complete URL, in that case when the user re-visits, then those resources will be served from the cache by the service worker if you have properly handled the fetch event (Don't worry, we have provided the code below).

    In your browser's developer tools, under the Application tab, there's a Service Worker section, which is where you will see your active Service Worker.

    application tab service worker option

    A service worker Javascript file should be inside the root directory of your site because a service worker will only work for the directory in which they exist.

    A service worker file located at /js/sw.js would only work for files in the /js directory.

    Important Service Worker Events

    Following are the three main service worker events that we should handle to properly implement service worker for our web application:

    1. install

    2. activate

    3. fetch

    Install Event

    This event is triggered when the web browser finds that the web application has a service worker JS file, and it begins to install a new service worker.

    Activate Event

    This event is triggered when the service worker is successfully installed and activated.

    Fetch Event

    This event is triggered when a request is made to the server to fetch resources for the web application, like HTML page, CSS file, JS file, some image or icon, etc.

    Write your First Service Worker JS

    To use a service worker on your web application, the first thing you have to do is register it with the web browser.

    The navigator object has a property serviceWorker, that has a method register(), which we will use to register the service worker.

    We want to run this method inside a script element and pass the path of our service worker file to it. The code for this is given below:

    navigator.serviceWorker.register('/sw.js');

    But because many old web browsers do not support service workers, hence it's always good to check if it's supported, first, and then do other things. Also, we can wait for the webpage window to load completely and then register our service worker (BEST PRACTICE).

    So the final code looks like this,

    // Check that service workers are supported
    if ('serviceWorker' in navigator) {
        // Use the window load event to register the service worker after the window load
        window.addEventListener('load', () => {
            navigator.serviceWorker.register('/sw.js');
        });
    }

    The above code checks if the browser supports the service worker, if yes, then it registers it.

    Handling Service Worker Install Event

    Below we have code for handling the service worker install event to create a new cache and store some files in the cache,

    const version = 'v1.1.'+new Date().getUTCDate();
    const CACHE_NAME = 'my-pwa-'+version;
    const CACHE_FILES = ['offline.html'];
    
    self.addEventListener('install', function(event) {
        event.waitUntil(
            caches.open(CACHE_NAME)
            .then(function(cache) {
                return cache.addAll(CACHE_FILES);
            })
            .then(function() {
                console.log("cached!");
            })
            .then(function() {
                self.skipWaiting()
            })
            .catch(function(err) {
                console.log("Error", err);
            })
        );
    });

    In the code above, we have created a cache in the browser with a name, and a version, which is required because time to time, we would want to expire the old cache and set a new one. We have stored the offline.html file in the cache. And we have defined the install event.

    Handling Service Worker Activate Event

    When we activate the service worker, we can do a couple of things like, if we want to remove any old cache, we can do that, or if we want to check some browser capabilities, we can do that.

    self.addEventListener('activate', function(e) {
        console.log("activated");
        // remove unwanted caches
        e.waitUntil(
            caches.keys().then(function(cacheNames) {
                return Promise.all(
                    cacheNames.map(function(cacheName) {
                        if (cacheName !== CACHE_NAME) {
                            console.log("Service Worker: clearing old cache");
                            return caches.delete(cacheName);
                        }
                    })
                );
            })
        );
    
    });

    In the above code, we are checking for any old cache and deleting it.

    Handling Service Worker Fetch Event

    Fetch is the most important event of service worker that can make or break your web application. Yes, if you handle it incorrectly, your website may never load in the browser, so be careful.

    In the fetch event, we intercept the HTTP request made by the browser, and then act upon it if required.

    For example, you can intercept requests to your website, see if the request is looking for some CSS file, that you have cached in the service worker, then you can directly serve it from the cache and don't send the request to the server.

    We can even provide complete response for a request from service worker and never let the request leave the browser for the server.

    self.addEventListener('fetch', (event) => {
        console.log("fetching");
        event.respondWith(
            caches.match(event.request)
            .then(function(response){
                if(response) {
                    return response;
                }
                else {
                    return fetch(event.request);
                }
            })
        )
    })

    In the code above, we are simply matching the request in the cache, if we can find the resource in the cache, we can return from there, or we can make the fetch call to let the request go to the server, like any other normal request.

    This is just an example, your use-case and requirements may vary, so plan what you want to do here as per that.

    The Final Step

    The last step is to include your service worker JS file in your website's page. So take the 4 pieces of code given above, copy-paste them in the same order in a file, name the file sw.js and store it in the root directory of your web application code.

    To include the sw.js file, add this in the head section of your index file or any other file for your webpage:

    <script src="sw.js"></script>

    And that's it. We are done.

    I like writing content about C/C++, DBMS, Java, Docker, general How-tos, Linux, PHP, Java, Go lang, Cloud, and Web development. I have 10 years of diverse experience in software development. Founder @ Studytonight
    IF YOU LIKE IT, THEN SHARE IT
    Advertisement

    RELATED POSTS