How to Uninstall, Unregister or Remove a Service Worker ⚙️ [With Example Code]

unregister-service-worker-heroSomething is going wrong in your service worker and you just want your site to work. So while you debug the problem how do you remove the service worker from existing clients?

The service worker life cycle is a concept that often confuses developers. We often cover registering and updating service workers, but neglect how to remove a registered worker from a web site.

Not knowing how to unregister a service worker from a client can leave your site in a suspended state of failure.

And no one wants their application to deliver a poor user experience...especially from a bug.

Unless you can quickly isolate and correct the issue you may need to buy some time to work through the error.

Removing the buggy service worker might be your best, temporary solution. This should at least eliminate the cause of the issue, while allowing the site to just work.

If you create a buggy service worker you want it to be on your local development machine, using a localhost web server. Unless you are a perfect developer you will encounter moments where your service worker is severely broken and may not update the way you want. Fortunately, when working locally you can control service worker registration through the developer tools.

Update on Reload

You first option is to check the 'update on reload' option. When this is selected the browser will always load the service worker file from the source (web server) as if the file changed. This can be done in the tools Application tab. Select the Service Workers node in the Chrome and Opera developer tools and you will see the service worker for your site.

chrome developer tools service worker update on reload service worker

Selecting this option should keep you from getting into a bind where your service worker wont update. Before committing your code or deploying to a server you should uncheck this option and test your application. By forcing a reload every time you could be masking a potential problem that needs to be corrected.

Manually Uninstalling A Service Worker

The next option is to manually unregister the service worker. This is also available from the developer tools. On the right-hand side of the service worker's detail you will see a line of links that manually trigger service worker actions. The last link is the Unregister link.

chrome-dev-tools-unregister-service-worker

FireFox does not, at this time, have an option to update when the page is reloaded.

unregister-service-worker-firefox

Selecting this link will unregister the service worker. Refreshing the page will start the service worker life cycle from scratch.

Just beware, unregistering the service worker does not purge the Cache. If you need to clear the Cache you should select it from the list and delete each cache.

FireFox, does have an option to unregister a service worker in their developer tools. To get there you need to open the 'about:debugging#workers' page. Here you will see all the registered service workers. Next to each one is an 'unregister' link.

Also, if you have a push notification subscription registered with the service worker, that subscription is revoked. The next time the service worker checks for the subscription it will prompt you to subscribe.

These are great tools for developers to manage their development process. But it will not help the average consumer.

Programatically Removing a Service Worker

Instead of registering a service worker you can replace that code with code to unregister a service worker. Remember you register a service worker in your page's JavaScript. Now, instead of registering a service worker, you will call unregister on the service worker's registration object.

(You will still want to feature detect for service worker support before executing the following code.)

  navigator.serviceWorker.getRegistrations().then(

    function(registrations) {

        for(let registration of registrations) {  
            registration.unregister();

        }

});

The getRegistrations function returns a promise that resolves a list of service worker registrations.

Loop over those registrations and all the registration object's unregister function. And voila your troublesome service worker is no longer registered.

The unregister function returns a promise that resolves a boolean. If the service worker was found and unregistered it returns true. If the service worker was not found it returns false.

If the service worker was not found that indicates it was already unregistered.

The service worker may not die immediately. If the worker is currently performing any tasks for a client it will complete before being officially removed.

For this to work the consumer will need to download your latest script. This could be problematic if you have cached the script using the service worker. For this reason it might be wise to keep the code that manages your service worker registration in a small, isolated file, that is not added to the service worker cache. You may also consider having a short Cache-Control time to live value as well.

The final option, if all else fails is to wait. Not the best answer, but within 24 hours your service worker will update.

That's because service workers are designed to phone home no matter what every 24 hours to see if there is a newer version available.

I call this the happy mom feature. Even if you have cached the service worker using the service worker, or have a very long time to live header so the service worker file is cached in browser cache, the browser will check the server after 24 hours since the last update.

Don't worry your customer devices will not be hitting your server every 24 hours every day. The rule is, if a service worker is instantiated, via a page load, push notification, etc, and has not checked for an update in the past 24 hours it will check the server for a new version.

So if your site is loaded once a week by the customer it will only perform this built in update check at that moment, not every day since the last visit.

This feature was added to the service worker specification as a fail safe measure. This means your worst case scenario is your service worker is broken for no more than 24 hours.

A Self-Cleaning Service Worker Removal Routine

Arthor Stolyar recently pointed out the standard removal process is not immediate. The code more or less queues up the removal of the service worker.

Just like registering a service worker does not immediately take control of the registering page, removal must wait for clients to refresh before unregistering.

Arthur points readers to a GitHub Gist where a service worker removes itself using the activate event.

self.addEventListener("activate", function(e) {

  self.registration.unregister()
.then(function() {

  return self.clients.matchAll();

})
.then(function(clients) {

  clients.forEach(client => client.navigate(client.url));

});

});

The key part of this code is the loop through all the active clients. As the code loops over each client it forces the browser to reload the page, which in theory should remove the service worker.

I like the approach, but think it may be a little flawed.

First, it assumes all the clients are browser tabs.

Service worker clients can be browser tabs and in most cases will be. However, a service worker client is any task that triggers a service worker event, like push or sync.

These are not browser tabs. In fact there are other new capabilities being discussed that would also operate completely separate from the browser process.

Instead I want to offer some modifications to the previous code:

self.addEventListener("activate", function(e) {

  self.registration.unregister()
.then(function() {

  return self.clients.matchAll();

})
.then(function(clients) {

  clients.forEach(client => {

    if (client.url && "navigate" in client){

        client.navigate(client.url))

    }

});

});

As you loop over each client it verifies if can be reloaded before attempting a navigation, which may throw an exception.

The next issue I see with the proffered code is executing this within the context of a new service worker, which must be registered first. I feel this sort of defeats the purpose of removing a service worker.

To remove a bad service worker, and by this I mean remove any service worker registration, it should be handled in the client.

Let's go back to the client registration code and apply the same principle:

navigator.serviceWorker.getRegistrations().then(

    function(registrations) {

        for(let registration of registrations) { 

            registration.unregister()
            .then(function() {

              return self.clients.matchAll();

            })
         .then(function(clients) {

              clients.forEach(client => {

            if (client.url && "navigate" in client){

                client.navigate(client.url));

            }

         });

        }

});

Now, instead of registering a new service worker you are just removing the registered service worker and not replacing it with another service worker.

If you goal is to replace a service worker then you can use the activate event to trigger an update to the different clients.

So the notion of a self-destructing service worker may not be the best concept to remove a service worker. I think the Gist was created more as an example of something that could be done.

It does demonstrate some important aspects of updating and removing a service worker. You will most likely need to update any live client being controlled by the service worker.

This is all part of a bigger concept of service worker life cycle management. I think this is a very complex topic that is often overlooked and marginally understood. That is why I spend a significant amount of time on the life cycle in my course Progressive Web Apps From Beginner to Expert.

I would also like to point out how disruptive this process can be. Before automatically reloading browser tabs you should notify the user first.

Note: I have not tested this code yet. I read Arthur's blog post and wanted to update this article as a quick response. As I can over the next day or so I will test my proposal and update as needed.

Summary

Hopefully you won't need to remove a service worker but bugs happen and it may be your only recourse. The code and techniques above should help get you out of the jam.

For development you probably want to use the developer tool method to unregister the service worker. But if you do ship a catastrophic bug you do have options to help your customers out. Always test your new service worker on a live, test site before shipping to production. Make sure to test on real devices too, so you know what your consumer's experience should be and to verify your changes or in this case service worker is removed.

progressive web app (PWA) beginner to expert online course

Do you want a much more detailed set of progressive web app and service worker tutorials? I just launched a new course, Progressive Web Apps : From Beginner to Expert.

This course covers everything you need to know to make any website a progressive web application. There are beginner topics to help anyone get started with progressive web app and service worker development. There are also modules to teach you how to polyfil many modern PWA features like offline and add to homescreen tactics.

Enroll today and save $171 off the $200 price. Progressive Web Apps : From Beginner to Expert is only $29 for a limited time.

Share This Article With Your Friends!