How to force a browser cache refresh after updating WAB app

430281
20
12-08-2016 02:26 PM
AdrianWelsh
MVP Honored Contributor

Hi, I am hoping there is a 'simple' answer for this as I have seen a few complicated answers. Long story short, I have a  Web AppBuilder app that I built through the Developer edition (2.1) and it is hosted on my website. After it is posted and loaded, if I update certain aspects of the app and change them on the web, they do not reflect due to the browser cache (as far as I am aware).

Robert Scheitlin, GISP‌ pointed me to a couple of very helpful threads but I feel like I need just a little more help so I am posting a new question (sorry GeoNet). 

In this thread,

Refreshing Web Appbuilder 

Stan McShinsky‌ asks how to refresh WAB. His conclusion was to edit that last few lines of the main index.html file to reflect this:

<script src="env.js?ver=1.1"></script>  
<script type="text/javascript" src="simpleLoader.js?ver=1.1"></script>  
<script type="text/javascript" src="init.js?ver=1.1"></script> 

He indicated he had little success with this, so I'm a little hesitant on making these changes. Question, what does adding "ver=1.1" do and what can improve this?

In this thread,

Automate Cache Clearing - Web App Builder 

Sam Libby‌ linked back to a stacked overflow post that mentions how to 'control web page caching' here:

http - How to control web page caching, across all browsers? - Stack Overflow 

This sounds like a good answer but I am not sure how to make the changes suggested in the SO post. There are many ways to "set" the change (including using PHP, node.js, ASP, Ruby, etc etc) but I am not skilled enough to know what change I need to make in my app. Question, can someone point me in the right direction on which change I need to make to my Developer Edition WAB application, based on the link above, on how to 'control web browser cache'? 

Since that thread was written eight years ago, would it be safe-ish to assume that changing the HTML4  code section would be the right answer?

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />

Thanks in advance and sorry for the long post!

20 Replies
JunshanLiu
Frequent Contributor

Now, there is a variable (deployVersion) in env.js to avoid cache.

Whenever you update your app, you can change this variable to avoid browser cache.

But there are still some limitations:

* The images and fonts in the css files may still be cached.

AdrianWelsh
MVP Honored Contributor

This sounds very promising. I haven't tested it yet but not sure I am doing this right.

I found the env.js file in the root folder of one of my apps. On line 81, this is written:

deployVersion = '2.2';

I currently have WAB 2.2. Does that mean I just need to change this variable (to anything or to something like 2.3 or 3) in order to make the app avoid browser cache?

0 Kudos
MichaelRobb
Honored Contributor

Does that mean I just need to change this variable (to anything or to something like 2.3 or 3) in order to make the app avoid browser cache?

I could never validate that this worked.

AdrianWelsh
MVP Honored Contributor

Looking at this further, that deployVersion variable is used towards the end of the script in a function called 'appendDeployVersion' (and that function is used twice above it) as indicated here:

global.avoidRequireCache = function(require){
 var dojoInject = require.injectUrl;
 require.injectUrl = function(url, callback, owner){
 url = appendDeployVersion(url);
 dojoInject(url, callback, owner);
 };
 };
global.avoidRequestCache = function (aspect, requestUtil){
 aspect.after(requestUtil, 'parseArgs', function(args){
 args.url = appendDeployVersion(args.url);
 return args;
 });
 };
function appendDeployVersion(url){
 if(/^http(s)?:\/\//.test(url) || /^\/proxy\.js/.test(url) || /^\/\//.test(url)){
 return url;
 }
 if(url.indexOf('?') > -1){
 url = url + '&wab_dv=' + deployVersion;
 }else{
 url = url + '?wab_dv=' + deployVersion;
 }
 return url;

But, I assume the only place that the variable should change would be in line 81 that says deployVersion is '2.2'.

MichaelRobb
Honored Contributor

using deployVersion does not work.

This 'deployVersion' is for appending the version to the URL, but in no way does this help if one deploys a web application to a web server (e.g. IIS), the users use their browsers and then you upgrade the app and re-point the IIS web application to the new (upgraded version) app.   

The user would type in the same URL... but this mentioned deployVersion doesnt force a browser refresh.  

I also tested this to validate... result was, users still loaded prior web app and had to force using browser manually.

pfoppe
by MVP
MVP

We were experiencing css files being cached in chrome (from disk).  It appears that chrome was not checking the ETag, cache-control, expires, or last-modified headers to determine if the .css files should be re-cached (as described here and here).  we tried manually adding headers in our IIS server and still no success getting chrome to re-load the .css files.  Forcing all the anonymous users to clear the cache or force refresh is not an option.  

Bottom Line: 

We updated the env.js deployVersion value and that did add the new value to the URI which does require chrome to load a new .css file (since it looks like a new resource).  Our plan is to update this deployVersion variable on deployment time to avoid the cache. So far its working well... 

Here was the URL being loaded from the cache: 

And when updating the deployVersion variable, the browser does "reload" the css file since it sees it as a new URL: 

AdrianWelsh
MVP Honored Contributor

Thanks Patrick, this is helpful. I'll have to check this out when I get back to this application!

MichaelRobb
Honored Contributor

For reference, the best approach I have found to work without ever having an issue is to do the following:

Add a clientCache control (in the web.config) and set the controlMaxAge to your desired time.

e.g. 

<!--expire after 1 day-->
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00"/>

daveostrander
Frequent Contributor

Hi Michael, just tried editing the web.config file using your supplied code. The only thing I changed was to change the time frame from 1 day to 5 minutes, and didn't seem to have any luck when using Chrome. It's possible I put the code in the wrong spot, in this case, within the staticContent tags. I tried a couple of other places, but that ended up breaking the application entirely. Since there is not that many spots to put it, is there something I am missing?

0 Kudos
daveostrander
Frequent Contributor

False Alarm. I believe that my Chrome browser just went to lunch. As is typical for me, I have a billion open tabs at all times, and usually they remain open for days on end. I believe that the browser just needed to be completely closed and that would have solved the issues I was seeing in Chrome. However, for those of you looking for a complete listing of the myriad of ways to control user caches (in IIS at least) this documentation lists them all.

My plan going forward will be to use the "Set Common HTTP Response Headers" in IIS manager and set the "Expire Web Content" to immediately (A.K.A. No Cache) on an individual application or on all of them depending on what has been updated, and then leave that in place for at least a few weeks to ensure that most if not all users will get the refresh. Once satisfied that everyone is now pointing at the newest version then I will simply flip the IIS setting back to once again improve application performance. 

Hope that helps

0 Kudos