Closed adam-t-b closed 5 years ago
In this project I separate self.skipWaiting
from window.location.reload
. So in service-worker.js
I have a message listener:
self.addEventListener('message', (e) => {
if (!e.data) return;
if (e.data === 'skipWaiting') self.skipWaiting();
});
and in registerServiceWorker.js
, in the updatefound
section, I have:
let refreshing;
navigator.serviceWorker.addEventListener('controllerchange', () => {
if (refreshing) return;
window.location.reload();
refreshing = true;
});
and in the updated
section:
const UpdatedEvent = new CustomEvent('swUpdated', { detail: registration });
document.dispatchEvent(UpdatedEvent);
So, when a new SW is detected, I create a new event with the SW rego as payload and send it to the document. In my app, I am listening for this event in a Main component, and when it comes, a function runs to change an alert boolean to true and set the rego prop on the Main component's data to the SW rego payload. The boolean is used to render an Alert component and the rego is sent as a prop. The Alert component thus appears on-screen and when you close it, a function runs that calls waiting.postMessage
on the rego object, with the message of skipWaiting
. The SW is listening for that to call self.skipWaiting
. When self.skipWaiting
is called, the new SW activates. This triggers the controllerchange
event that we are listening for in registerServiceWorker
, and that is where we call reload
.
@jamessouth This is a better solution. I didn't think about putting the event listener for controllerchange directly in the registerServiceWorker.js. I added it to mine, and it negates the need for another hook. Great suggestion! This issue can probably be closed.
😊😁👍
I'm currently using the pwa plugin in 'InjectManifest' mode since that's the only way I could find to add an event listener for messages on the service worker. So far, this has been useful when we want to skip waiting on user input. For example, I prompt a user when there's an updated service worker. Something like this:
However, I'm trying to figure out how to reload the page after the user clicks refresh. I can't do the following because the service worker has no context of the window object. its out of scope
My thought was to add a new hook or to re-use the 'ready' hook in register-service-worker which would be triggered whenever the installing worker state === 'activated'
For example:
This would allow the ability to reload the page safely from the registerServiceWorker.js file after a user has clicked 'Refresh'
Am I overthinking this? Perhaps there's a better way to handle this?