DEV Community

Let Users Know When You Have Updated Your Service Workers in Create React App

Gert Glükmann on January 04, 2020

Show an alert component when you have pushed a new service worker, allowing the user to update their page right away Create React App (CRA) is g...
Collapse
 
tomas223 profile image
Tomas Hornak • Edited

Great article. It helped me finally understand serviceWorkers.

After some more digging I started to wonder if it wouldn't be better to avoid storing ServiceWorkerRegistration and retrieve one when needed.
Should I concern that object can "expire" after some longer time?

I came to this:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.ready.then(registration => {
        const registrationWaiting = serviceWorkerRegistration?.waiting;
        ...
    });
}
Collapse
 
glukmann profile image
Gert Glükmann

Well yeah, when user doesn't click the Update button then maybe should think about the "expiring". Should test it out. Retriving it when needed probably would be safer solution?

Collapse
 
tomas223 profile image
Tomas Hornak

I will use your example for now and will see in future if there are any issues with it. If yes I will come back to report it :)

Collapse
 
ataraxis profile image
Florian Dollinger

Thanks! One problem here is that redux stores are not persistent. So if the user is pressing "refresh" on its browser instead of activating the waiting serviceworker, then the dialog wont pop up again. I solved that by

1) using redux-persist
2) not storing the the activated serviceworker inside the store, but getting it on the onClick() of the "update" button, just like this (very similar to Tomas Hornaks post, thank you too):

  const activateUpdate = () => {
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.ready.then(registration => {
        const serviceWorkerWaiting = registration.waiting;

        if (serviceWorkerWaiting) {
          console.log("inside waiting...")
          serviceWorkerWaiting.postMessage({ type: 'SKIP_WAITING' });
          serviceWorkerWaiting.addEventListener('statechange', e => {
            if (e.target.state === 'activated') {
              dispatch(swUpdateDone());
              window.location.reload();
            }
          });
        }
      });
    }
  }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
sebastijandumancic profile image
Sebastijan Dumancic

Awesome stuff Gert, just implemented this and it works wonderfully. Potential bug is when user lands on the website with new SW waiting, but refreshes (or has open other tabs), after first showing of the notice to reload, it won't show up again and old service worker will still be visible.

But that's edge case, since that user will still get the new SW next time he lands on the website.

Either way, this really helped solve reloading. Thanks!

Collapse
 
wallaceturner profile image
wallaceturner

thanks Gert, I think your code should be included the CRA boilerplate

Collapse
 
manuelurbanotn profile image
manuelurbanotn

Hello Gert, nice post!
I'm working with a legacy app with and older version of CRA.
Can you share the workaround for older versions you mentioned before?

Collapse
 
glukmann profile image
Gert Glükmann

Hi!
You have create another file where you add the eventListener for message yourself (as shown in one of the gists) and then append that file to created service worker on build time. This can be done for example with github.com/tszarzynski/cra-append-sw.
Let me know if you have any troubles.

Collapse
 
manuelurbanotn profile image
manuelurbanotn

Hi Gert!
Finally I noticed that my app has Workbox integrated to Webpack, so I fixed it adding skipWaiting: true on my Webpack config.

Thanks for your time!

Thread Thread
 
niketsoni profile image
Niket Soni

Hey buddy! Thank you so much for your comment here. It worked for me like magic :)

Collapse
 
kingmauro profile image
Mauro

Hi Gert. Just what I was looking for. I just have one problem. It seems I cant pass the 'reg' argument from .register() to Redux so I can use it later on my Router. Any help would be great. Thanks

Collapse
 
glukmann profile image
Gert Glükmann

Hi. I would need to see the code to help. Can you create a public repo or use codesandbox.io/?