Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My PWA web app keep showing old version after a new release on Safari (but works fine on chrome)?

I added PWA and service worker to my existing web app based on Angular 5. Everything looks fine on first release. However, when I try to release updates, something strange is happening.

On PC using Chrome, I don't have problem. After each release, I got an alert asking me to update for a new version, which is great.

However, this alert is missing on iOS, which is probably okay because iOS doesn't support auto update yet as I understand it. If I use Chrome on iOS, I can get the new version after manually refresh it (sometimes it takes a few refreshes). However, Safari browser doesn't normally show the new version. If I keeps refreshing the page, the new version comes up eventually, but it falls back again after I close and reopen it. As I play around, the only way I get to the new version is to manually clear the Safari cache first. This is not acceptable to regular user.

I understand iOS has limited support of PWA, but is this the most what we can get on iOS? Without the auto update, how can an iOS user know of the new release and update it?

like image 539
newman Avatar asked Jul 20 '18 05:07

newman


People also ask

Does PWA work on Safari?

On desktop, Safari and Firefox do not support PWA installation. They do support offline capabilities, but the experience will always start within the browser user interface. It may get fullscreen, but never a standalone window on desktop.

How do I force refresh PWA?

You can launch a PWA from your home screen, do what you have to do with it, then launch another app, and go back to the PWA the next day. If you haven't closed the app or turned off your phone in the meantime, it will not reload the page — instead it will simply allow you to continue your session where you left off.

Does PWA automatically update?

Yes. If you don't cache it, then browser would do a regular http call - not proxied via service worker. You can even case that JS file and check for update on opening the app, refresh the app if there is a update.

Which browser does PWA use?

At present, PWAs can be installed through the browser in Windows 10, Windows 8 and Windows 7. They can be installed using Google Chrome and Microsoft Edge (Chromium-based only). Both Google Chrome and Microsoft Edge (Chromium) will soon include mainstream support for running a PWA at start-up.


2 Answers

I found and posted the answer here, but to re-iterate:

After weeks and weeks of searching, I finally found a solution:

  1. I add a check for versionstring on the server, and return it to the app.

  2. I look for it in localtstorage (IndexedDB) and if I don’t find it, I add it. If I do find it, I compare versions and if there is a newer one on the server, I throw up a dialog.

  3. Dismissing this dialog (my button is labeled "update") runs window.location.reload(true) and then stores the new versionstring in localstorage

Voila! My app is updated! I can't believe it came down to something this simple, I could not find a solution anywhere. Hope this helps.

UPDATE SEPT 2019:

There were a few problems with the technique above, notably that it was bypassing the PWA service worker mechanisms and that sometimes reload would not immediately load new content (because the current SW would not release the page). I have now a new solution to this that seems to work on all platforms:

forceSWupdate () {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.getRegistrations().then(function (registrations) {
      for (let registration of registrations) {
        registration.update()
      }
    })
  }
}

And inside my serviceworker I now throw up the dialog if there is an update, and do my location.reload(true) from there. This always results in my app being refreshed immediately (with the important caveat that I have added skipWaiting and clientsClaim directives to my registration).

This works on every platform the same, and I can programatically check for the update or wait for the service worker to do it by itself (although the times it checks vary greatly by platform, device, and other unknowable factors. Usually not more than 24 hours though.)

like image 86
Stephen Avatar answered Oct 20 '22 03:10

Stephen


after trying many solutions, calling registration.update didn't make it for me. Only this one is working for me :

const forceReload = () =>
  navigator.serviceWorker
    .getRegistrations()
    .then((registrations) =>
      Promise.all(registrations.map((r) => r.unregister())),
    )
    .then(() => window.location.reload())

The strategy :

  • write a version number in the new deployed app (ie: x.x.x)
  • listen to a version number served on a webSocket
  • call forceReload when they don't match

That way any user connected or not stays up to date with the latest version.

Hope it'll help someone.

like image 28
bossno Avatar answered Oct 20 '22 03:10

bossno