Popular question How do I uninstall a Service Worker? has a fine answer for unregistering a service worker using JavaScript. How can I get the service worker to clear any named caches when it unregisters?
From MDN unregister
, The service worker will finish any ongoing operations before it is unregistered. So, it sounds like it should be possible to listen for an uninstall
event, but no such event exists as far as I can tell. For giggles, I tried adding self.addEventListener('uninstall', ...)
to the service worker, but as expected, it did not fire on unregister. I also tried listening for any message
that might be sent on unregister... no dice.
I also considered watching the service worker state, but none of installing
, installed
, activating
, activated
, and redundant
appear relevant. Not to mention, it doesn't look like message passing to the service worker is possible, so I'm not sure what I'd do with an uninstalling
state from outside the service worker anyways.
Reaching for straws, while I see references to an uninstalling flag, I haven't seen it exposed anywhere. Suggestions?
The following code should unregister all service workers and clear out everything in the Cache Storage API for your origin:
async function unregisterAndClearCaches() {
const registrations = await navigator.serviceWorker.getRegistrations();
const unregisterPromises = registrations.map(registration => registration.unregister());
const allCaches = await caches.keys();
const cacheDeletionPromises = allCaches.map(cache => caches.delete(cache));
await Promise.all([...unregisterPromises, ...cacheDeletionPromises]);
}
Using the Clear-Site-Data
header is another option for "forcing" everything to be cleared (service worker registration, caches, etc.) in a single action.
This can be accomplished with message passing. One reason I prefer this to the answer by Jeff Posnick is that the name of the cache does not need to be known outside of the service worker. In the service worker, add a message listener:
self.addEventListener('message', (event) => {
messageHandler(event);
});
The messageHandler()
can then take action on various passed messages. For example:
function messageHandler(event) {
if (event.data === 'purge_cache') {
caches.delete('mycache')
.then((success) => {
console.log("Cache removal status: " + success);
})
.catch((err) => {
console.log("Cache removal error: ", err);
});
}
}
To trigger this action, post the message from your script on a page that is under the service worker's scope. So, for the original question of how to delete the cache and then unregister the service worker, you could do this:
navigator.serviceWorker.getRegistration()
.then((registration) => {
registration.active.postMessage('purge_cache');
registration.unregister()
.then((success) => {
console.log('Service worker unregistration status: ' + success);
})
.catch((err) => {
console.log('Service worker unregistration failed', err);
});
})
.catch((err) => {
console.log('Service worker registration not found.');
});
Notice, I did not wait for a successful reply from postMessage('purge_cache')
; from MDN unregister
, "The service worker will finish any ongoing operations before it is unregistered."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With