Refreshing a cached Angular SPA

2019-04-30 09:05发布

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?

1条回答
Explosion°爆炸
2楼-- · 2019-04-30 10:02

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'
});
查看更多
登录 后发表回答