[Solved] PWA force refresh when new version released?



  • @ssuess I made a function that refreshed it a long time ago.
    But since iOS 11.12 update just completely screwed up PWA support and keeps refreshing the app every time you open, I just stopped PWA all together now.

    Also, I’ve had many problems always with users not on the latest version. Sometimes safari webkit doesn’t recognise and trigger the popup to refresh to get the latest version of the app and I was never able to find out why.



  • @ssuess Anyway, if you look in service-worker-prod.js in the PWA source folder you will find this line:

    case 'installed':
    

    That’s where you need to write your logic. I had:

    case 'installed':
      // At this point, the old content will have been purged and the
      // fresh content will have been added to the cache.
      // It's the perfect time to display a "New content is
      // available; please refresh." message in the page's interface.
      if (!window.QNotify) {
        window.location.reload()
        break;
      }
      window.QNotify({
        message: window.store.getters.text.global.newVersionAvailable,
        timeout: 10000,
        type: 'info',
        actions: [{
          label: window.store.getters.text.global.refresh,
          handler: function () { window.location.reload() }
        }]
      })
      break;
    


  • @mesqueeb I am curious what you mean about “keeps refreshing the app every time you open”, because this definitely does NOT happen in my PWA on iOS (unless I have something else wrong with it like an invalid cert or mismatched domain). In my testing, I had actually mistakenly thought refreshing was fixed because it seemed to be getting the latest version but then realized my test domain was invalid and thus was never operating as a PWA anyway. Once i tested back on the valid domain it went back to caching all the time. As I said above, the only way I have found to get my PWA to refresh is to paradoxically clear the SAFARI cache. (which obvi makes ZERO sense to a user or anyone else).



  • @ssuess Thanks for your post.
    I meant this comment in this post:

    What to have in mind
    Your PWA won’t keep state between sessions, if the user gets out of a PWA, it will be restarted when coming back, so if you need the user to validate an email, SMS or do a two-factor authentication, have that in mind to offer a proper solution.

    It was the same for me, where every time I open the PWA it will flash and take me back to the homepage. Maybe they fixed this already?

    Combined with this, not getting the prompt to install the latest service worker and having users using older versions of my apps without me being able to do anything about it just added to the list of problems… That’s why I left PWA’s.



  • @mesqueeb Oh I see what you mean. Yes in fact, I am taken back to the homepage, but because everything is cached, all info on that homepage and other pages (and of course what I am storing in IndexedDB) is still the same, ie no new version or page changes are downloaded, despite being directed to the main page on every PWA launch/load. So other than a navigational inconvenience, it still won’t check for new version of PWA. 😞



  • @ssuess Exactly… iOS really f*cked up the PWA support this time…

    I believe they want to make the worst compatibility as possible to make devs not use PWA’s and make more native apps. Because Apple won’t make money from PWA’s and they have more chances they will from native apps.

    Welcome to the world where money is more important than the consumers.



  • It is really a shame. And a search around the web has very little information of this type (ie clear descriptions of what is and is not supported), and no word from Apple on when or if they will ever support the missing pieces. My guess is they will not unless there is a huge outcry, for exactly the reasons you mention (ie they won’t make money from it).



  • OMFG!!! I have 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 ok button is labeled “update”) runs window.location.reload(true) and then stores the new versionstring in localstorage

    RESULT: My app is updated!! I have been searching for a way to do this for weeks and weeks, so glad it finally works on iOS. Hope this helps someone else.



  • @ssuess thank you for add your solution, I have implemented it with Vuex and works fine.



  • @ssuess @israel965 can you post a bit more detail please? I’m having the exact same problem, but I haven’t worked at that lowlevel with quasar yet.

    If i wanted to just add a button to manually force update, without the version check… (I would have to tell users to push it of course but…)
    window.location.reload(true)

    this is the magic code that actually busts the cache and reloads everything?

    • do you manually create a version string each time you do a new version deploy somewhere or does the quasar build / webpack process generate some type of hash you can use easily?

    • the localStorage method you use, does quasar wrap these APIs? if using VueX does vueX have an option to push data to localStorage?

    Thanks for any help.



  • @dcsan window.location.reload(true) will clear the cache, but unless you have the updated version up on the server, it will just reload the same thing. The fact of publishing a new version in quasar (and then uploading it to the server) sets all the unique cache signatures. While on android the PWAs will automatically update when those signatures change, on iOS this was not the case, because the app would never check. So running window.location.reload(true) forces the app to delete its cache and check again, this time finding the new version (and loading and caching it). As for the localStorage method I use, it is via the localForage plugin (https://github.com/shidianxia/vue-localforage). I just store a simple versionstring in my localStorage and compare that against one I set on the server and retrieve each time I update (this is separate from the cache signatures that Quasar sets within the code). If the version on the server is newer, I clear my local cache and reload (Otherwise I leave it alone because I don’t want to needlessly reload my app all the time, only when there is a newer version). Hope this helps.



  • thanks for the response! and tip on localForage, tho it’s a callback based API which I don’t really prefer.
    I also found this writeup
    https://deanhume.com/displaying-a-new-version-available-progressive-web-app/

    are there any version info in the app available from the quasar webpack build process? otherwise I’m thinking to put something into my deploy pipeline to write a JSON file with the current epoch time into /public folder and then check against that. no need to put that into the DB just deploy the file and load from client as a static JSON.



  • localForage can be used via promise or callback, FYI.



  • Quasar also provides a localstorage API:
    https://quasar-framework.org/components/web-storage.html


Log in to reply