Reputation: 39593
Service Workers can interfere with the refresh button (by design). On desktop Chrome, you can hold shift and click the refresh button to do a hard reload, ignoring any installed ServiceWorker.
Is there a way to force a reload ignoring the SW in JavaScript?
(I want this so I can give mobile users a button to push if the SW starts misbehaving. Phones don't have a shift key.)
Upvotes: 14
Views: 7737
Reputation: 39593
If you unregister
the Service Worker before refreshing, the next page load will load without the Service Worker.
navigator.serviceWorker.getRegistration().then(function(reg) {
if (reg) {
reg.unregister().then(function() { window.location.reload(true); });
} else {
window.location.reload(true);
}
});
Upvotes: 17
Reputation: 39340
Here is an example of what I commented on:
page script:
if('serviceWorker' in navigator){
// Register service worker
navigator.serviceWorker.register('/service-worker.js')
.then(
reg =>
console.log("SW registration succeeded. Scope is "+reg.scope)
,err =>
console.error("SW registration failed with error "+err)
);
}
const send_message_to_sw = (msg) =>
new Promise(
(resolve, reject) => {
// Create a Message Channel
const msg_chan = new MessageChannel();
// Handler for recieving message reply from service worker
msg_chan.port1.onmessage = (event) => {
if(event.data.error){
reject(event.data.error);
}else{
resolve(event.data);
}
};
// Send message to service worker along with port for reply
navigator.serviceWorker.controller.postMessage(
msg
, [msg_chan.port2]
);
}
);
document.body.addEventListener(
"click"
,()=>
send_message_to_sw(
{
action:"delete"
,cache:/^v1$/
,url:/.*bundle.js$/
}
)
.then(
(msg)=>
console.log("deleted:",msg)
)
);
Service worker:
console.log("SW Startup!");
// Install Service Worker
self.addEventListener(
'install'
,(event)=>
console.log('installed!')
);
// Service Worker Active
self.addEventListener(
'activate'
,(event)=>
console.log('activated!')
);
self.addEventListener(
'fetch'
,(event) =>
event.respondWith(
caches.match(event.request)
.then((resp) =>
resp
||
fetch(event.request)
.then(
(response) =>
caches.open('v1')
.then(
(cache) => {
cache.put(event.request, response.clone());
return response;
}
)
)
)
)
);
self.addEventListener(
'message'
,(event) =>{
const data = event.data || {};
if(data.action === "delete"){
var p =
caches.keys()
.then(
(keyList) =>
keyList
.filter(
key=>data.cache.test(key)
)
)
;
if(data.url === undefined) {
p = p.then(
(keyList) =>
Promise.all(
keyList
.map((key) =>{
caches.delete(key);
return key;
}
)
)
)
}else {
p = p.then(
(keyList) =>
Promise.all(
keyList
.map((key) =>
caches.open(key)
.then(
(cache)=>
Promise.all([
cache
,cache.keys()
])
)
.then(
([cache,items])=>
Promise.all(
items
.filter(item=>data.url.test(item.url))
.map(
item=>{
cache.delete(item);
return key + ":" + item.url
}
)
)
)
)
)
)
}
return p.then(
(keys)=>
event.ports[0].postMessage(
keys
.reduce(
(acc,item)=>acc.concat(item)
,[]
)
)
);
}
}
);
Upvotes: 1