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?
I found and posted the answer here, but to re-iterate:
After weeks and weeks of searching, I finally found a solution:
I add a check for versionstring on the server, and return it to the app.
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.
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.)