232

After deleting /serviceworker.js from my root directory, Chrome still runs the service worker that I removed from my webroot. How do I uninstall the service worker from my website and Chrome so I can log back into my website?

I've tracked the issue down to Service Work's cache mechanism and I just want to remove for now until I have time to debug it. The login script that I'm using redirects to Google's servers for them to login to their Google account. But all I get from the login.php page is an ERR_FAILED message.

Piper
  • 1,266
  • 3
  • 15
  • 26
Mark Tomlin
  • 8,593
  • 11
  • 57
  • 72

20 Answers20

441

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.

425nesp
  • 6,936
  • 9
  • 50
  • 61
Daniel Herr
  • 19,083
  • 6
  • 44
  • 61
  • 2
    I had to add "use strict"; before this code to make it work. – codeKonami Jan 21 '16 at 15:46
  • 11
    Is there anytime time-based around this? Say a user visited once, registered the worker, and hasn't come back since, do I need to keep this snippet in our codebase forever just in case? – loganfsmyth Aug 02 '16 at 18:45
  • How do I re-register service worker after unregistering it? – Avery235 Dec 31 '17 at 03:58
  • 4
    Verbose version: https://gist.github.com/mrienstra/9c60a76009480e2240770dadb2fb96fe – mrienstra Feb 04 '18 at 22:11
  • @Avery235 You would then need to add code back to your web page's script to register the new, hopefully not broken :), service worker. – Chris Love Feb 12 '18 at 13:59
  • 12
    I have a blog post reviewing this and other service worker remove/uninstall options https://love2dev.com/blog/how-to-uninstall-a-service-worker/ – Chris Love Feb 12 '18 at 13:59
  • execute the code in the console。raise error,Uncaught (in promise) DOMException: Failed to get ServiceWorkerRegistration objects: The URL protocol of the current origin ('chrome-search://local-ntp') is not supported. cannot execute in the console? – Richard Chan Apr 20 '18 at 14:51
  • @RichardChan `getRegistrations.then(...)` cannot be used on HTTP. Make sure you are on HTTPS before you call this function. E.g. check `location.protocol`. – Nux Apr 20 '18 at 15:03
  • To delete the service worker: copy the answer code into chrome console on the page where your service worker is – thedanotto Jan 08 '19 at 22:26
  • 8
    How would that help? The page is already cached by the installed worker and your new script will never be fetched by the users. – riv Aug 02 '19 at 16:50
  • This code leads to an error in IE11. It doesn't support for..of. It's better to use for...in. – Sergey Beloglazov Aug 07 '20 at 10:15
  • 2
    The following article discusses a potential issue with this answer's code and suggests an alternative: https://medium.com/@nekrtemplar/self-destroying-serviceworker-73d62921d717 – sammy34 Oct 22 '20 at 09:08
  • The ServiceWorker is still active and running after calling ``registration.unregister()`. So this does not actually work like expected, does it? – Chilly Code Aug 26 '21 at 09:09
  • Bump @sammy34's comment. For me, this approach didn't work but NekR's project worked. I wrote notes here: https://github.com/NekR/self-destroying-sw/issues/10#issuecomment-1312973827. – josephdpurcell Nov 14 '22 at 03:00
128

You can also go to the URL: chrome://serviceworker-internals/ and unregister a serviceworker from there.

Asim K T
  • 16,864
  • 10
  • 77
  • 99
k00k
  • 17,314
  • 13
  • 59
  • 86
  • 12
    You can type this into dev console to unregister all of them in one fell swoop. `document.querySelectorAll(".unregister").forEach(item=>item.click())` – senbon Jun 08 '19 at 13:34
  • However, if you have other visitors that you need to unregister as well (friends, users, project managers, etc.), the answer above (by Daniel Herr) is more of an effective solution. You've also got Firefox, Edge and Safari, as well, in flavors of iOS, Android, macOS, Windows 10 for each to test. – Steven Ventimiglia Jul 20 '19 at 20:25
  • $$('.unregister').forEach(item => item.click()) – Travnikov.dev Mar 11 '20 at 13:34
50

You can do this through Chrome Developer Tool as well as Programatically.

  1. Find all running instance or service worker by typing

    chrome://serviceworker-internals/

    in a new tab and then select the serviceworker you want to unregister.

  2. Open Developer Tools (F12) and Select Application. Then Either

    Select Clear Storage -> Unregister service worker

    or

    Select Service Workers -> Choose Update on Reload

  3. Programatically

if(window.navigator && navigator.serviceWorker) {
  navigator.serviceWorker.getRegistrations()
  .then(function(registrations) {
    for(let registration of registrations) {
      registration.unregister();
    }
  });
}
Sakshi Nagpal
  • 1,003
  • 7
  • 16
24

In Google Chrome, you can go to Developer tools (F12) -> Application -> Service worker and unregister the service workers from the list for that specific domain.

Screenshot

This method is effective in development mode of a site and mostly they run on localhost which is you may need for other project's development.

Community
  • 1
  • 1
Asim K T
  • 16,864
  • 10
  • 77
  • 99
8

FYI, in case you are using MacOS Safari browser, there is one way to forcibly unregister a service worker (steps and images for Safari 12.1):

  1. Safari > Preferences... > Privacy > Manage Website Data… Safari Preferences : Privacy

  2. Enter domain name (ex. 'localhost'), click "Remove" Safari Preferences : Privacy : manage website data

Note: In addition to service workers, this also will erase all caches, cookies, and databases for this domain.

terrymorse
  • 6,771
  • 1
  • 21
  • 27
  • Looks like this doesn't work if the service workers were installed via a Private Window. – aris Mar 06 '20 at 13:47
  • @aris that's irritating giving Apple should be transparent, it is not even clear about the common websites' installed service workers. – Machado Dec 22 '22 at 20:03
7

In addition to the already correct answers given, if you want also to delete the SW cache you can invoke the following method:

if ('caches' in window) {
    caches.keys()
      .then(function(keyList) {
          return Promise.all(keyList.map(function(key) {
              return caches.delete(key);
          }));
      })
}


More in this article (Paragraph: "Unregister a service worker")


Another possibility, via Browser, is by accessing the "Cache Storage" section and click on the "Clear Site Data" button:

enter image description here

Francesco
  • 9,947
  • 7
  • 67
  • 110
5

You should detecte two API in your devices: getRegistrations and getRegistration. The service-worker not has a unique set of APIs in all platforms. For example, some browsers only have a navigator.serviceWorker.getRegistration, no navigator.serviceWorker.getRegistrations. So you should consider with both.

GuoX
  • 421
  • 5
  • 8
3

safely uninstall Service Worker

if ('serviceWorker' in navigator) {
      navigator.serviceWorker.getRegistrations().then(function (registrations) {
        for (const registration of registrations) {
          // unregister service worker
          console.log('serviceWorker unregistered');
          registration.unregister();
        }
      });
    }
Pankaj Rupapara
  • 752
  • 4
  • 9
3

to detect service worker:

navigator.serviceWorker.controller

Code to for deletion of service worker:

navigator.serviceWorker.getRegistrations()
  .then(registrations => {
    registrations.forEach(registration => {
      registration.unregister();
    })
  });

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

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

  if ('caches' in window) {
      caches.keys()
        .then(function(keyList) {
            return Promise.all(keyList.map(function(key) {
                return caches.delete(key);
            }));
        })
  }

  if ('serviceWorker' in navigator) {
        navigator.serviceWorker.getRegistrations().then(function (registrations) {
          for (const registration of registrations) {
            // unregister service worker
            console.log('serviceWorker unregistered');
            registration.unregister();

            setTimeout(function(){
              console.log('trying redirect do');
              window.location.replace(window.location.href); // because without redirecting, first time on page load: still service worker will be available
            }, 3000);
          }
        });
      }
Vitalij
  • 662
  • 2
  • 12
  • 26
3

IF your service worker don't let you update your files. You will need to replace serviceworker file (sw.js / ServiceWorker.js) with the next 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))
    });
});

Source here

3

as for me , i just use a new nonexistent scope service worker to replace old one,

ServiceWorker: {
        events: true,
        // what range of URLs a service worker can control. Use a nonexistent path to disable ServiceWorker
        scope: '/disable-service-worker/',
      },

as for the app.js, i add below code to unregister old sw:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.getRegistrations().then(registrations => {
    for (const registration of registrations) {
      // keep only serviceWorker which scope is /disable-service-worker/, The purpose is to make serviceWorker useless
      if (registration.scope.includes('/disable-service-worker/') === false) {
        registration.unregister()
      }
    }
  });
  // clear cache of service worker
  caches.keys().then(keyList => {
    return Promise.all(
      keyList.map(key => {
        return caches.delete(key);
      }),
    );
  });
}
danny wang
  • 39
  • 4
3

If, like me, you need to unregister a service worker after deploying an entirely new codebase at the same domain (without a service worker), the solution is to create a new service worker at the same location and disable all caching:

self.addEventListener('fetch', event => event.respondWith(fetch(event.request)))

This way, when the browser asks for sw.js (or whatever you named it), it will get the new one, then load your new site from the network. After an indeterminate time (i.e. after all your users have loaded the new service worker), you can remove the service worker.

jstaab
  • 3,449
  • 1
  • 27
  • 40
2

It can also be done in Chrome through application tab: enter image description here

Michael Nelles
  • 5,426
  • 8
  • 41
  • 57
1

This code is compatible with Internet Explorer:

if (navigator.serviceWorker) {
    navigator.serviceWorker.getRegistrations().then(                
        function(registrations) {
            for (let idx in registrations) {
                registrations[idx].unregister()
            }
        })
}

IE doesn't support 'for...of' and 'for...of' construction may lead to "'SCRIPT1004: Expected ';'" error

Sergey Beloglazov
  • 342
  • 1
  • 3
  • 14
1

The other answers all add code to the live website to remove the service worker. However I didn't want to leave that live code running forever so I developed a solution that works from within the service worker itself. The steps are below, I posted more detail and explanation on my blog.

  1. Delete the code that registers the service worker.
  2. Replace the service worker script with the following file. The new code must be available from the same URL the previous service worker was at. If you had multiple service worker URLs in the past you should duplicate the code at all of them.
console.log("Cleanup Service Worker Starting");

caches.keys()
    .then(keys =>
        Promise.all(
            keys.map(async key => console.log("caches.delete", key, await caches.delete(key)))))
    .then(async () => {
        console.log("registration.unregister", await registration.unregister());
    })
    .then(() => console.log("DONE"))
    .catch(console.error);

This code is fairly straight forward. First it deletes all the caches, then it unregisters itself.

Users' browsers will automatically check for an updated service worker the next time they load your website, or the next event 24h after the last service worker check. This means that existing users will run this cleanup on their next visit.

Kevin Cox
  • 3,080
  • 1
  • 32
  • 32
1

If You want to unregister all of the registered service workers in Browser, you can do it by opening ex.

  • Chrome: chrome://serviceworker-internals/
  • Brave brave://serviceworker-internals/

open DevTools > Console and paste this:

$$('.unregister').forEach(b => b.click())
devzom
  • 676
  • 1
  • 9
  • 19
1

I'm using Brave. None of the provided answers worked for me on a page with a single service worker.

  • navigator.serviceWorker.getRegistrations() stays pending.
  • navigator.serviceWorker.getRegistration() stays pending.
  • navigator.serviceWorker.getRegistration(navigator.serviceWorker.controller.scriptURL) stays pending
  • navigator.serviceWorker.ready is fulfilled immediately unless there is no service worker registered for the current page

I used this:

(await navigator.serviceWorker.ready).unregister()
SgtPooki
  • 11,012
  • 5
  • 37
  • 46
0

Open this page: chrome://serviceworker-internals and click to unregister button.

If you want to unregister all service worker open the developer tools and run this code on above page.

document.querySelectorAll("button.unregister").forEach(item=>{ item.click()})
Kadir
  • 76
  • 4
0

Open in Chrome

chrome://serviceworker-internals/?devtools

then F12 in Console

$$('.unregister').forEach(b => b.click())

Valentin Petkov
  • 1,570
  • 18
  • 23
0

Typical JavaScript loop thats compatible with everything:

navigator.serviceWorker.getRegistrations().then(function(registrations) {
    var registrationslength = registrations.length;
    for (var i = 0; i < registrationslength; i++) {
        registrations[i].unregister();
    }
})
Jeff Luyet
  • 424
  • 3
  • 10