Keep a Single-Page-Application updated

Mattia Costamagna
3 min readDec 17, 2020

--

Photo by fatty corgi on Unsplash

If you are a web developer in 2020, you’ve probably heard of Single-Page-Applications and if you haven’t, this is what they are:

In a SPA, all necessary HTML, JavaScript, and CSS code is either retrieved by the browser with a single page load, or the appropriate resources are dynamically loaded and added to the page as necessary, usually in response to user actions. The page does not reload at any point in the process, nor does it transfer control to another page, although the location hash or the HTML5 History API can be used to provide the perception and navigability of separate logical pages in the application. [Wikipedia]

Building SPA is generally a good idea but it has some downsides, one of which is that users might use your application without ever refreshing the page, so if you update your code and deploy a new version, you may experience errors due to the using an outdated version.

There are many ways to ensure that the application gets updated; You might want to force the refresh of the page as soon as the new version gets deployed, or maybe you just want to notify your users that a new version is available and they need to manually refresh the page. Sometimes you can’t force a refresh because users could be in the middle of compiling a form, and if that happens they would have to start over. I’ve searched the Internet looking for solutions used by other people to solve this problem and I found this great article that gave me the idea on how to build a function that does this job. I ended up going for a solution that is slightly different from the one I found because in my case I don’t have any “flows where we rely on information being preserved in the Vuex store in between route navigations”, and I’m fine with a solution that performs a reload of the page when the route changes.

So basically my idea is to periodically check if there is a new version stored on the backend. I use React to build frontends along with Create-React-App to create the bundle that needs to be deployed. I know that every time I generate the bundle I get different unique hashes for each resource, so I can periodically check if one of the resource names has changed to know that a new version is available. Here’s the JavaScript function that performs this check:

Using fetch I can get the raw index.html file stored on the backend, convert the output to a text string and then searching for the main JavaScript resource using a RegEx (here is a nice website to test your RegEx). After that I just have to loop the script tags in the body of the local index.html looking (again) for the main script. The function returns true if the src attributes are different.

Now we have to periodically call this function.

In the componentDidMount method I create a new timer that every 10 minutes calls the CheckForIndexHTML and stores its return value in the reloadOnNextChange variable. I have to keep checking for updates until I know that there is a new version, so if the return value is true, I can clear the interval and stop the timer. The history prop is provided by react-router-dom and it exposes a listen function that executes a callback every time the route changes. So I can use this function to perform a reload of the page if I have to.

Conclusion

These few lines of code allow my web application to update itself without bothering users with notifications asking them to reload the page. People won’t notice anything wrong when they see the page reload because they are used to wait while navigating from one page to another. Of course it all depends on what your application does, and there could be cases where this solution is not the best but I hope this little trick will help you; let me know if you know a better way to do this!

--

--

Mattia Costamagna

I love dogs, Bruce Springsteen, programming, Netflix, and dogs!