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.)
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.)
Share Improve this question asked Oct 23, 2017 at 4:19 Dan FabulichDan Fabulich 39.6k42 gold badges145 silver badges184 bronze badges 2 |2 Answers
Reset to default 17If 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);
}
});
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)
,[]
)
)
);
}
}
);
window.location.reload(true)
(theforcedRefresh
parameter), is generally supposed to be equivalent to shift-refresh, but in my tests,location.reload(true)
doesn't override/ignore the SW; as far as SWs are concerned, it's the same aslocation.reload(false)
. (Is that a bug in Chrome??) – Dan Fabulich Commented Oct 23, 2017 at 4:20caches.delete
developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/… You could communicate with the service working from your js code (button click handler) and the service worker message handler could delete the caches (or only some). When the service worker is done then reload the page: craig-russell.co.uk/2016/01/29/… – HMR Commented Oct 23, 2017 at 8:13