fgerschau / comments

1 stars 0 forks source link

create-a-pwa-update-notification-with-create-react-app/ #11

Open utterances-bot opened 3 years ago

utterances-bot commented 3 years ago

PWA Update Notification with Create React App

Learn how to trigger update notifications that ensure that your users are using the latest version of your Progressive Web App.

https://felixgerschau.com/create-a-pwa-update-notification-with-create-react-app/

jamiehaywood commented 3 years ago

Thanks very much for this article Felix, I found it particularly useful in understanding how to make my CRA service worker work better on my PWA :) Would be good if you could update it for CRA 4, and their new service worker approach!

fgerschau commented 3 years ago

Thanks for the feedback :smile:

I'll have a look into CRA and see what I need to update, maybe it's worth writing a new article on that topic.

Tuguldur007 commented 3 years ago

Thanks your great work brother. Yeah CRA 4 removed default serviceWorker.unregister(); line from its index file.

Would be good if you could include webserver first strategy and not caching, only for reminding page has new update and customer choose when to refresh and get latest version due to doing some important task

Tuguldur007 commented 3 years ago

serviceWorker.unregister(); separated by template installation.

MattisAbrahamsson commented 3 years ago

Thanks a lot for writing this article!

One problem I have found is that the notification will only show the first time the page is loaded after an update has been deployed, so if you reload the page the notification will dissapear, I guess this is because the onUpdate method will not run as the new service worker is already in the queue.

Any idea how to solve this?

Edit: I solved it by modifying my service worker file to accept an onInit function which is run on service worker initialization

fgerschau commented 3 years ago

Thanks for the feedback!

@mattisabrahamsson awesome, I didn't know how to solve this. I have to try this out and update the article accordingly 😄

@tuguldur007 I'll try CRA 4 and maybe even write a new article on this, thanks :)

MhmdNdri commented 3 years ago

Thanks for the Article. I am using a workbox to create my service worker and handle caching, is your solution work in that situation? If not, do you know any way to send update notifications via workbox?

fgerschau commented 3 years ago

@MhmdNdri CRA is actually using workbox under the hood. If you auto-generate your service worker, you should be able to follow this tutorial without any issues.

In case you create the service worker yourself, you need to make sure to include the following code snippet:

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});
joelpoloney commented 3 years ago

@MattisAbrahamsson Do you mind sharing your onInit function changes so the notice always appears?

mihaif7 commented 3 years ago

Greate article! Only problem I have is that I don't know how to disable caching for the service-worker.js file. How do you disable chacing for service-worker.js?

fgerschau commented 3 years ago

@mihaif7 that depends on where you are hosting these files.

Here is a tutorial on how to do this with AWS for example. If you are using Cloudflare, you would need to create a page rule to not cache this file.

Since there are so many possible ways of hosting your application, I can't possibly cover all of them in this article.

mihaif7 commented 3 years ago

@fgerschau Thank you for the quick reply. I tought I had issues with service-worker.js caching but it was something else :)

Do you have any suggestions regarding the fix mentioned by @MattisAbrahamsson? I'm new to service workers.

Edit: After a bit more research I found a way to show the reload banner even after a reload. I added the following lines of code in the registerValidSW() function in the serviceWorkerRegistration.js after this function. (I'm using the generated files from CRA 4) @joelpoloney

registration.onupdatefound = () => {}
if (registration.waiting !== null) {
   if (config && config.onUpdate) {
       config.onUpdate(registration);
   }
}

Also if you want to get the notification even if you don't reload the page you can add the following lines in App.js (should be inside the router). [1] [2]

 const history = useHistory();

  useEffect(() => {
    history.listen((location, action) => {
      // check for sw updates on page change
      navigator.serviceWorker
        .getRegistrations()
        .then((regs) => regs.forEach((reg) => reg.update()));
    });
  }, []);
MattisAbrahamsson commented 3 years ago

@joelpoloney Sure thing, It was a very small and simple change, but so far it has worked flawlessly for us.

All I did was add this onInit function

navigator.serviceWorker
    .register(swUrl)
    .then(registration => {
        if (config?.onInit) {
            config.onInit(registration);
        }
...
mleister97 commented 2 years ago

Thanks a lot for this tutorial.

@MattisAbrahamsson could you please provide your full solution?

mleister97 commented 2 years ago

Wouldn't a better solution be to use localStorage (to keep the value of showReload) and populate the local showReload state on reload with the value from localStorage?

tsiory commented 2 years ago

is the old caches overwritten by the new one when we update like this ?

paul-rchds commented 2 years ago

Hi, thanks for the article. The one thing I am not sure of is what you mean by this: "Very important: You have to disable caching for the /service-worker.js file..."

aquibbaig commented 2 years ago

Sometimes I get this message saying "Failed to update a ServiceWorker for scope ('{{hostname}}/') with script ('{{hostname}}/service-worker.js'): An unknown error occurred when fetching the script.". Able to reproduce it sometimes when I have the app open across multiple tabs. Any fix?

fgerschau commented 2 years ago

@paul-rchds please check out my answer above regarding disabling cache for the service worker file.

@aquibbaig I'm not sure what the issue is here. If you find an answer, please feel free to share it here so others can learn from it as well 😄

aquibbaig commented 2 years ago

Sure, it was very simple actually. I was using setInterval() to poll for sw updates. I set my Cache-Control headers for ./sw.js as max-age=0, no-cache, no-store, must-revalidate, so that it will no cache the service worker. When I make a release, it takes some time to build the app. So, the service worker that calls update() is not able to fetch the new one. Took a while to figure it out

fgerschau commented 2 years ago

@aquibbaig thanks for sharing 🙌

aquibbaig commented 2 years ago

Thank you so much for this article Felix! I also documented my experience for people who want to learn more about how to take it to production. Y'all can find notes here https://www.aquibbaig.in/posts/pwa-update-notification

ittaboba commented 2 years ago

Hi, thanks a lot for this tutorial. I have a use case that I am not 100% sure it's covered: assuming the user has multiple clients open, window reload can happen on just one. What happens to the others? Are they updated? Do they need to be refreshed manually to actually download the updates?

Krush159 commented 2 years ago

Hi, Could you please guide how to make this work if one is using webpack 4 for creating react app and not using CRA?