9

Basic setup: Angular 1.5 SPA served from Apache 2.4 backed by a REST api also served from Apache 2.4.

I have read every technique available to allow a SPA to be fresh and updated after some application code is changed on the server.

Solutions come via HTTP caching (HTTP headers) or cache busting (versioning file names for example) techniques. All of them are based on the web browser making a request to get a resource and having some mechanism to know if the content needs to be updated or can be served from cache.

The main problem with SPAs is that requests for resources are not ususally made after intital load since the web app is happy loaded in the browser and only XHR calls to backend are initiated to load data. In many cases a user does not close the tab for many days with the inconvenience of having files not being refreshed for a long time.

The hardest problem is the index.html file (see this post). This one is called only once the first time you load the app in the browser and then it is never requested. Only a manual browser page reload can init a second request for this file.

All javascript and css files are loaded after a request for index.html, and then are never reloaded. Only a new request for index.html can refresh them.

If no requests to get index.html are made after initial load, how cache-control headers or cache busting strategies can allow javascript or css files to refresh when they change on server?

I'm affected two ways by this problem:

  1. The REST API must be compatible with the web app. If I introduce a breaking change in the API and the user does not reload the page it could trigger an error of leave data inconsistent.

  2. Since html files can reload while javascript or css files not doing it, an incompatible html file can be served (with missing CSS class definitions or scope references for example).

The only real solutions I have found are:

  1. this answer
  2. checking in every XHR call for the current deployed version, and check if it is diferent from the version loaded in the browser,

but:

  1. It seems a lot of overhead to keep everything versioned (database, API, server code, client code) when in the vast majority of situations everybody will be in the same version.
  2. It will be very user unfriendly, having a message telling that the whole app will be reloaded and missing all the data not saved in backend. Think of filling a form and after pressing save be forced to reinput all data again.

I am missing something in how everybody is handling Angular caching?

David Casillas
  • 1,801
  • 1
  • 29
  • 57
  • Have you found a solution for this one, I am running in the exact problem minus i am using knockout not angular – Loredra L Sep 07 '17 at 11:12
  • Hi did you find a satisfied solution? I didn't and I asked a similar question here https://softwareengineering.stackexchange.com/questions/423068/options-to-notify-users-single-page-application-spa-static-resources-have-upda – Qiulang Mar 06 '21 at 04:22
  • I added a header to all API requests with the expected API version. In the API the header is checked against the current API version and if it does not match an error is returned. When the front end detects the error it asks the user to reload the browser. – David Casillas Mar 09 '21 at 10:28

1 Answers1

-1

You can use URL Query Parameters to aid you. What we do in our application is to append a query parameter at the end of resources ( script, images ) and update it for next major release. Example :

<script src="angular.js?v=1.1"/>

And after next major release, change it to

<script src="angular.js?v=1.2"/>

This change forces the web server to request the new file as URl is new.

Most of large angular apps are back up by require.js which provides its own configuration to deal with caching problem. Example :

require.config({
    baseUrl : 'resources/app',
    urlArgs : 'v=1.2'
});
Gaurav
  • 3,614
  • 3
  • 30
  • 51
  • 4
    This is not my question. I know how to bust static files but if index.html file is not reloaded their url is not updated with this new param and no request for this files is made so they are not reloaded. – David Casillas Jun 29 '17 at 11:39
  • Can you configure web server to always serve fresh content for index.html and put no-cache headers in it ? – Gaurav Jun 29 '17 at 11:47
  • 1
    Any of these solutions need that the browser starts a request for `index.html` file, but in a single page application this is done only the first time the web is loaded in the browser. Then only internal routing is made to change views and sometimes to load some html, but no index.html nor css or javascript files are requested again. The web can live days in the browser with the index.html file not being requested as long as the tab is not closed or a manual browser reload is started. – David Casillas Jun 29 '17 at 11:51
  • 1
    The best answer I found about it was this one: https://stackoverflow.com/a/44772047/4519548 Where he basically says there is no special function to do that. You'll have to check constantly if the published version is the same as the client's version. And ask the user to reload if it is different. I think `location.reload(true);` does the trick to reload the page. – Rick Wolff Oct 19 '17 at 16:02
  • I am using @RickWolff 's suggestion to add a button with onclick='location.reload(true);' to reload index.html along with app.js containing angular.module(). – etoricky Aug 28 '19 at 03:16