What I am trying to achieve:
render page with loader/spinner
if
service-worker.js
is registered and active, then check for updates- if no updates, then remove loader
- if
updatefound
and new version installed, then reload the page
- else register
service-worker.js
- when
updatefound
, meaning new one was installed, remove loader
- when
I am using sw-precache
module for me to generate service-worker.js
and following registration code:
window.addEventListener('load', function() {
// show loader
addLoader();
navigator.serviceWorker.register('service-worker.js')
.then(function(swRegistration) {
// react to changes in `service-worker.js`
swRegistration.onupdatefound = function() {
var installingWorker = swRegistration.installing;
installingWorker.onstatechange = function() {
if(installingWorker.state === 'installed' && navigator.serviceWorker.controller){
// updated content installed
window.location.reload();
} else if (installingWorker.state === 'installed'){
// new sw registered and content cached
removeLoader();
}
};
}
if(swRegistration.active){
// here I know that `service-worker.js` was already installed
// but not sure it there are changes
// If there are no changes it is the last thing I can check
// AFAIK no events are fired afterwards
}
})
.catch(function(e) {
console.error('Error during service worker registration:', e);
});
});
After reading the spec it is clear that there are no handlers for something like updatenotfound
. Looks like serviceWorker.register
checks if service-worker.js
changed internally by running get-newest-worker-algorithm, but I cannot see similar methods exposed via public api.
I think my options are:
- wait for couple of seconds after service worker registration becomes active to see if
onupdatefound
is fired fire custom events fromservice-worker.js
code if cache was not updated
Any other suggestions?
Edit:
I've came up with some code which solves this issue by using postMessage()
between SW registration and SW client (as @pate suggested)
Following demo tries to achieve checks through postMessage
between SW client and SW registration, but fails as SW code is already cached DEMO
Edit:
So by now it looks like I cannot implement what I want because:
- when service worker is active you cannot check for updates by evaluating some code in SW - this is still the same cached SW, no changes there
- you need to wait for
onupdatefound
, there is nothing else that will notify of changes in SW activation
of older SW comes beforeonupdatefound
- if there is no change, nothing fires after
activation
- SW registration
update()
is immature, keeps changing,Starting with Chrome 46, update() returns a promise that resolves with 'undefined' if the operation completed successfully or there was no update
- setting timeout to postpone view rendering is suboptimal as there is no clear answer to how long should it be set to, it depends on SW size as well