Search code examples
javascriptcachingrollup

How to make sure the browser read the latest static files immediately


I serve the static webapp on aws s3 that distributed through CDN (aws cloudfront). The files are ES6 based build version with rollup. For short info, except index.html rollup will generate new hash files every build the webapp. So the files are always unique every update, except index.html. Then on the aws cloudfront I put the index.html into invalidation cache list.

Well then, I will expect users always request the latest version of the webapp with that approach. Yes it works, but with a little note!

So once there is new updates, the browser is still loading the old index.html file on the first time. I have to refresh page to push the browser get the latest index.html. It's not good for the end users. They doen't want to know about refreshing, most will not know right?

One last experiment, I added small script inside on index.html to perform version validation like so :

  <script>
    fetch('/version.json').then(r => {
      if (r.status == 200) {
        return r.json()
      } else {
        alert("Found server updated, let us resync the contents!")
        location.reload(true)
      }
    }).then(j => {
      if (window.localStorage.getItem("app-version")) {
        if (j.version != window.localStorage.getItem("app-version")) {
          alert("Found server updated, let us sync the contents!")
          window.localStorage.setItem("app-version", j.version)
          location.reload(true)
        }
      } else {
        window.localStorage.setItem("app-version", j.version)
      }
    })
  </script>

That script worked as expected but wondering whether I will have better solution out there? Kindly to have another idea, please?

Expected behavior

Browser have knowledge the latest index.html immediately without any refresh/reload page from end users.

Thank you


Solution

  • I would take advantage of a service-worker to make it easier and more efficient to load and cache a cohesive version of the app.

    The service worker has a built in mechanism for checking whether the app has been updated, which is does each time the app is launched.

    What it won't do is trigger that check for you while the app is running. While you could poll regularly to check for updates, it's more efficient for both your server and users to have them subscribe for updates which you can do using something like Firebase RTDB (Real Time Database):

    When you publish a new version and want to immediately force all running instances to update, you change the version or timestamp that they are subscribing to and have that trigger the service-worker update check, which then refreshes and reloads the app.

    There are lots of available patterns for prompting users about any update in case they are in the middle of completing a form etc...