The Kotive web app pulses the server every 5 minutes to check if any new version of the app has become available in the meantime.

Until recently, we displayed a notification when an improved version of the app became available. The person needed to click the “Refresh now” button in order to refresh the page and get the latest version of the web app.

When the page refreshed, a brand new version of the web app would be loaded from the server and the person would then proceed with the task they wanted to do next. This new version was then cached in the browser for faster access in future.

After getting feedback that the notification sometimes interferes with the task they’re busy with, we set out to find a new way of refreshing the web app without interruption.

Now, when a new version is available, no notification is shown. Instead, the app waits for the person to navigate to a new “page” and then reloads the app. No interaction from the person is required and it poses no interruption in the user interface (besides the few seconds the new app takes to load).

How we refresh Kotive’s Single Page Application

It’s quite popular to use Service Workers to check for updates but we’ve already had a check in place and only needed to change a couple of lines of code.

1) We set a timer to check for updates every 5 minutes.

const appUpdateAvailable = false
setInterval(checkForUpdates, 300*1000)

2) We then make a HEAD request to our manifest.json (generated by our javascript bundler) and check if the ‘last-modified’ timestamp in its response header is equal to the timestamp we stored in localstorage the last time we checked.

export const checkForUpdates = ()=> {
  $.ajax({
    url:            '/manifest.json',
    method:         'HEAD',
    contentType:    'application/json; charset=utf-8',
    dataType:       'json',
    cache:          false
  }).done( (data, textStatus, jqxhr)=> {
    const storedLastModified  = localStorage.getItem('last-modified')
    const lastModified        = jqxhr.getResponseHeader('last-modified')
    if (storedLastModified == null) {
      localStorage.setItem('last-modified', lastModified)
    } else if (storedLastModified !== lastModified) {
      appUpdateAvailable = true
    }
  })
}

3) If a new version of the web app is available, we simply refresh the page the next time the web app’s route has changed and forces it to ignore any cached files.

if (appUpdateAvailable) window.location.reload(true)