How to Uninstall a Service Worker

How do I uninstall a Service Worker?

Removing Service Workers Programmatically

You can remove service workers programmatically like this:

navigator.serviceWorker.getRegistrations().then(function(registrations) {
for(let registration of registrations) {
registration.unregister()
} })

Docs: getRegistrations, unregister

Removing Service Workers Through The User Interface

You can also remove service workers under the Application tab in Chrome Devtools.

Unregistering/Removing a Service Worker

I stumbled across this answer which seemed a better-than-most solution.

Blog Post: https://medium.com/@nekrtemplar/self-destroying-serviceworker-73d62921d717

Github: https://github.com/NekR/self-destroying-sw

It destroys itself with this code:

self.addEventListener('install', function(e) {
self.skipWaiting();
});

self.addEventListener('activate', function(e) {
self.registration.unregister()
.then(function() {
return self.clients.matchAll();
})
.then(function(clients) {
clients.forEach(client => client.navigate(client.url))
});
});

Here's an even more in-depth explanation and further improvement on the above code.
https://love2dev.com/blog/how-to-uninstall-a-service-worker/

How to unregister and remove old service worker?

You should specify why you want to unregister the Service Worker.

I suppose there are two possibilities:

  • You want to get rid off the /service-worker.js file and remove SW completely
  • You want to have a new/updated SW and replace the previous one

First case:
Checkout this answer: How do I uninstall a Service Worker?

Second case:
You don't have to unregister the old SW, you just update the code in /service-worker.js and register it on top of the old one. This is the usual scenario. The new, updatet SW will takeover and the obsolete will go away.
I suggest you read these tutorials very carefully:
https://developers.google.com/web/fundamentals/instant-and-offline/service-worker/lifecycle
https://developers.google.com/web/fundamentals/getting-started/primers/service-workers

I'm stressing carefully since it's very easy to get SW related stuff wrong and completely bork your website :)

How can I remove a buggy service worker, or implement a kill switch ?

I wanted to expand on some of the other answers here, and approach this from the point of view of "what strategies can I use when rolling out a service worker to production to ensure that I can make any needed changes"? Those changes might include fixing any minor bugs that you discover in production, or it might (but hopefully doesn't) include neutralizing the service worker due to an insurmountable bug—a so called "kill switch".

For the purposes of this answer, let's assume you call

navigator.serviceWorker.register('service-worker.js');

on your pages, meaning your service worker JavaScript resource is service-worker.js. (See below if you're not sure the exact service worker URL that was used—perhaps because you added a hash or versioning info to the service worker script.)

The question boils down to how you go about resolving the initial issue in your service-worker.js code. If it's a small bug fix, then you can obviously just make the change and redeploy your service-worker.js to your hosting environment. If there's no obvious bug fix, and you don't want to leave your users running the buggy service worker code while you take the time to work out a solution, it's a good idea to keep a simple, no-op service-worker.js handy, like the following:

// A simple, no-op service worker that takes immediate control.

self.addEventListener('install', () => {
// Skip over the "waiting" lifecycle state, to ensure that our
// new service worker is activated immediately, even if there's
// another tab open controlled by our older service worker code.
self.skipWaiting();
});

/*
self.addEventListener('activate', () => {
// Optional: Get a list of all the current open windows/tabs under
// our service worker's control, and force them to reload.
// This can "unbreak" any open windows/tabs as soon as the new
// service worker activates, rather than users having to manually reload.
self.clients.matchAll({type: 'window'}).then(windowClients => {
windowClients.forEach(windowClient => {
windowClient.navigate(windowClient.url);
});
});
});
*/

That should be all your no-op service-worker.js needs to contain. Because there's no fetch handler registered, all navigation and resource requests from controlled pages will end up going directly against the network, effectively giving you the same behavior you'd get without if there were no service worker at all.

Additional steps

It's possible to go further, and forcibly delete everything stored using the Cache Storage API, or to explicitly unregister the service worker entirely. For most common cases, that's probably going to be overkill, and following the above recommendations should be sufficient to get you in a state where your current users get the expected behavior, and you're ready to redeploy updates once you've fixed your bugs. There is some degree of overhead involved with starting up even a no-op service worker, so you can go the route of unregistering the service worker if you have no plans to redeploy meaningful service worker code.

If you're already in a situation in which you're serving service-worker.js with HTTP caching directives giving it a lifetime that's longer than your users can wait for, keep in mind that a Shift + Reload on desktop browsers will force the page to reload outside of service worker control. Not every user will know how to do this, and it's not possible on mobile devices, though. So don't rely on Shift + Reload as a viable rollback plan.

What if you don't know the service worker URL?

The information above assumes that you know what the service worker URL is—service-worker.js, sw.js, or something else that's effectively constant. But what if you included some sort of versioning or hash information in your service worker script, like service-worker.abcd1234.js?

First of all, try to avoid this in the future—it's against best practices. But if you've already deployed a number of versioned service worker URLs already and you need to disable things for all users, regardless of which URL they might have registered, there is a way out.

Every time a browser makes a request for a service worker script, regardless of whether it's an initial registration or an update check, it will set an HTTP request header called Service-Worker:.

Assuming you have full control over your backend HTTP server, you can check incoming requests for the presence of this Service-Worker: header, and always respond with your no-op service worker script response, regardless of what the request URL is.

The specifics of configuring your web server to do this will vary from server to server.

The Clear-Site-Data: response header

A final note: some browsers will automatically clear out specific data and potentially unregister service workers when a special HTTP response header is returned as part of any response: Clear-Site-Data:.

Setting this header can be helpful when trying to recover from a bad service worker deployment, and kill-switch scenarios are included in the feature's specification as an example use case.

It's important to check the browser support story for Clear-Site-Data: before your rely solely on it as a kill-switch. As of July 2019, it's not supported in 100% of the browsers that support service workers, so at the moment, it's safest to use Clear-Site-Data: along with the techniques mentioned above if you're concerned about recovering from a faulty service worker in all browsers.

How to use Angular's safety-worker.js to uninstall Service Worker?

You just have to rename safety-worker.js to ngsw-worker.js on the production and keep it there for a while (say, until the majority of the app users get this update)



Related Topics



Leave a reply



Submit