Skip to Content
Technical Articles

SAP UI5 Cache Buster Technique for Non-ABAP Based SAP UI5 Applications

Introduction:

SAP UI5 cache buster usually works and designed  for the ABAP Net-viewer based UI5/Fiori Applications.

How this process works: It usually loads the resources with a timestamp or the versions embedded along with all the file names. At the time of loading the application a timestamp must be binded with the file names, so if we reload the application it checks the timestamp difference and it brings back the new changes(i.e. clears the cache), so that we will be able to see the newly made changes in the application without having to do the empty cache and hard refresh.

Non-ABAP Net viewer Based SAP UI5 Applications: SAP has designed this cache buster for only ABAP based net-viewer developments as it brings the sap-ui-cachebuster-info.json from the platform which will have the individual timestamps that is been binded for every file which helps in mapping at the time of reload.

So if we do the SAP UI5 application development out of the ABAP support/scope like MII and others, this cache buster technique will not work in those application. so the main issue will be the End Users will have to do the Empty cache and hard refresh every time whenever a new change or release to a application is been made.

For this i have created a flow which does the same process as the cache buster, which requires a version maintenance for the UI5 applications.

ADVANTAGES: At the time of reload This will only refresh the new resources only if the version is been changed newly as mentioned in the below process. Else it loads the application quicker.  This method we can use for any UI5 applications even when its used in ABAP based platforms as we can have a control over the release measures and we can reduce the unwantedly bringing of new resources as time based

Step 1:

Create a version.json file in your application folder and maintain the versions and change respectively whenever a change is made. and have a code like below.

 

{ "_TheAppVersion": "1.0" }

 

Step 2:

In your Index.html file, if you have a attachInit function add the below code, if you do not have one, create the attachInit function and attach to the core.

For SAP UI5 Versions 1.56 and Below :

For the UI5 applications below 1.56 version use the below code snippet and it works as all the resources for the UI5 applications loads via JQuery so it appends the version number that we have to all the files that are loaded.

 

 sap.ui.getCore().attachInit(function () {

            //force update on page load if version changed - i.e. app cache buster
            $.post( "/XMII/CM/TheApp/version.json?"
                + "&__=" + new Date().getTime()
                , function(data){
                    $.ajaxSetup({
                        data: {
                            _TheAppVersion: data._TheAppVersion
                        }
                    });
                    var theapp = new sap.ui.core.ComponentContainer({
                        name : "TheApp",
                        height : "100%"
                    });
                    theapp.placeAt("content");
                    return;
                }
                , 'json'
            );
        });

For SAP UI5 Versions Above 1.56 :

For the UI5 applications above 1.56 version use the below code snippet and it works as only some of the resources is loaded by JQuery and some others are being loaded by the UI5loader which does not loads the files like above. So we added the below code by Overriding XMLHttpRequest.open()

This below code checks for the resources file by file and appends the version to it if not added. This method works independent of the loaders that SAP UI5 uses which differs version to version
	sap.ui.getCore().attachInit(function () {

		//force update on page load if version changed - i.e. app cache buster
		//Appending version to files 
		// created by (Bhanu Siddhardhan)
		$.post("./version.json?" + "&__=" + new Date().getTime(), function (data) {
			(function () {
				var proxied = window.XMLHttpRequest.prototype.open;
				window.XMLHttpRequest.prototype.open = function () {
					var url = arguments[1];
					if (url.indexOf("?") == -1) {
						url = url + "?";
					}
					arguments[1] = url + "&_TheAppVersion=" + data._TheAppVersion;
					return proxied.apply(this, [].slice.call(arguments));
				};
			})();
			new sap.m.Shell({
				app: new sap.ui.core.ComponentContainer({
					height: "100%",
					name: "XMII.CM"
				})
			}).placeAt("content");
			return;
		}, 'json');
	});
 

Step 3:

Whenever a change is made to the code just open the version.json file that you have crated in your application and update the versions. And then if the user reloads and if the version that he has and the version that is currently updated is different it will go ahead and reload the entire resources freshly. You will be able to see the changes.

Versions appends to the files like below.



Conclusion:

This cache buster works even for the ABAP based UI5 application, This is custom developed method to handle the work of cache buster. If we want to control the versioning by our self, we can try and use this even in ABAP based applications.

This is the only solution for handling the cache buster for the non ABAP based SAP UI5 applications.

 

/
8 Comments
You must be Logged on to comment or reply to a post.
    • Thanks for your tip both Bhanu and Christian, i used the method described by Christian ( as below ) since it worked best for me. What i will like to do is to append instead of an APP version, the modied date of the resource loaded. In this way only the needed resorces are reloaded and the user will not be forced to reload everything. in which way you would modify the code in order to get the resource last modification date ?

       //$.ajaxSetup({ data: { _TheAppVersion: data._TheAppVersion }});
                      (function() {
                      var proxied = window.XMLHttpRequest.prototype.open;
                      window.XMLHttpRequest.prototype.open = function() 
                      {
                      var url = arguments[1];
                      if(url.indexOf("?") == -1){ url = url + "?"; }
                      arguments[1] = url + "&_TheAppVersion=" + data._TheAppVersion;
                      return proxied.apply(this, [].slice.call(arguments));
                            };
      • Hi Filippo,

                    I like the way in which you are approaching the performance optimization of loading only the files with new version that is having the updates, But when we come to a SAP standard where you get the timestamps by default when you run the app by deploying the same in Fiori Launchpad. Even as a standard practice, SAP follows the version for entire project rather than doing it at the file level. This ensure the versioning of the Apps at APP level and Not at the FILE level which is always good to follow.

  • Hi,

    it is great, the users really appreciate it, in theorie.
    In practise it does not work for my .controller.js files (which i realised too late).


    It seems the controller is loaded differently, not via jquery but via ui5loader, also the type is not "xhr" but "script".

    My UI5-Version is 1.71.38 and i guess my component is attached a little differently, not via attachInit-Script...
    ... which I am now going to check if it has anything to do with controller loading.

    In the meantime... any Ideas how to get this to work for me?

    • Hi Lars,

      Good day! Can you please paste the attachInit function which you have written, in my writeup I have mentioned two ways of doing this, and make sure that you have done the one which is designed for versions 1.56 and above.

      • Oh nice, thanks for the quick reply.

        Did a GET for the version.json instead of POST, because post was not allowed, but it doesn't seem to be the problem.

        <script>
        	sap.ui.getCore().attachInit(function () {
        		$.get(
        			"version.json?" + "&__=" + new Date().getTime()
        			, function (data) {
        				(function () {
        					var proxied = window.XMLHttpRequest.prototype.open;
        					window.XMLHttpRequest.prototype.open = function () {
        						var url = arguments[1];
        						if (url.indexOf("?") == -1) {
        							url = url + "?";
        						}
        						arguments[1] = url + "&_AppVers=" + data._AppVers;
        						return proxied.apply(this, [].slice.call(arguments));
        					};
        				})();
        			}, 
        			'json'
        		);
        	});
         </script>​

        /
        • Ok, so i have got another app, where the Shell and Component-Container are attached in the attachInit function, just like your example.


          And it's working there.
          Noticing the type of controller request is "xhr" here, not "script".

          I guess problem solved, or at least workaround found.

          Anyway, thank you very much for holding hands Bhanu.

          Have a nice day!

          /
          • Hi Lars,

            Thats Great! I was looking forward to say the same, if the booststrapping is done with the correct mapping of component container, then this method would work! Have a happy coding.