cancel
Showing results for 
Search instead for 
Did you mean: 

UI5 Components: Component-preload.js

js2
Product and Topic Expert
Product and Topic Expert
0 Kudos

When using Components in UI5 apps I can see a stray GET request each time the application is loaded looking for Component-preload.js in the app directory.

There is a little bit of explanation on preloading in the SDK help (but not much). From what I can gather: library pre-loading is something thats only applicable to the SAP-provided UI5 libraries. Our own code can't execute till the UI5 libraries are loaded anyway

I've tried setting data-sap-ui-preload="async" (sync is the default); but then UI5 won't load. Interestingly if I set sap-ui-preload=auto as a url query string parameter; the app seems to load normally (sync) and there is no stray GET on the Component-preload.js file.

Does anyone have any further information on pre-loading and why there is a GET request on this file and the best way to stop it.

If you also know how to stop all the message bundle GET's that would be interesting to know as well.   😉

Accepted Solutions (1)

Accepted Solutions (1)

AndreasKunz
Advisor
Advisor

Hi Jason,

this Component-preload.js is the next step of performance improvements (by reduction of requests).

In a previous step, the library-preload.js files per control library bundled all controls of the library into one JSON file containing only strings. This file is loaded in advance (hence "preload") and the code of each control was then parsed on-demand.

This preload file can only be produced by our internal (complex) Maven-based build and by the Control development tools in Eclipse which I think are not available outside yet, either. We are currently moving away from this build to a simpler build that can be used outside as well (think Grunt) and eventually this feature should be availabe for your control libraries as well.

The Component-preload.js does a similar thing, but on application level: all the Views and Controllers and helper classes can cause a lot of requests, and they are bundled in a similar way, hence the similar name. Again, this build step is currently not available outside, but should eventually be.

We are indeed still experimenting how to do it best. A big question is how to further optimize the loading of controls: loading entire libraries is not optimal, especially when only controls from each library are needed. But when you package only the initial needed stuff, should further controls then again be loaded on demand, one-by-one?? Too many requests. Or should all resources ever possibly needed in an app be loaded initially? But what does this mean for Apps like the Fiori Launchpad which actually can load many other apps/components? Load the total superset in advance? Or how to build delta packages without an active server-side component which would make UI5 depend on certain server technologies?

For simpler, smaller, isolated apps a build step that would optimize the result a lot would be quite possible and maybe that's what we should do first.

Regards

Andreas

js2
Product and Topic Expert
Product and Topic Expert
0 Kudos

Thanks for that detailed response Andreas - it all makes sense with that.

As for performance optimization (which seems to be the biggest issue for UI5 based on the discussions I'm having with other developers):

With a little re-work, could we not just use script tags to include each control we want to use instead of having to load an entire library and without the need for parsing a preload json file. We could then use standard web tools (with grunt, gulp, etc) to minify an concat resources and so on... and only ever include exactly what we need which miniises the size of the resources and the number of GET requests...

Regards...

AndreasKunz
Advisor
Advisor
0 Kudos

Yeah, well, basically yes, but what about the CSS? You want to do the same for the single control CSS files? And also for the single script files that are normally merged into sap-ui-core.js?

And how will you know which other JS files and controls the used controls depend on? When using sap.m.List, you'd need to remember to also include sap.m.ListBase script, to give just one very obvious example.

I think such a process that is based on manual configuration on this granularity can quickly become much too cumbersome.

Instead of this, the dependencies should be built on a require/declare mechanism - which they actually already are. This mechanism is now moved towards requireJS. And with a bit more parsing, those tools you mention can then again be used to do the optimization. Same for the CSS files: we are going to use LESS imports to declare which files should be concatenated. And build tools can easily resolve these imports then.

Another thing: in the Ctrl-Alt-Shift-P (or S) tools, you can already find a list of all currently loaded UI5 modules (=files), so an optimization could also be based on this list, retrieved after a test run of the application. And in fact we had also built a download configurator like that of jQuery UI which uses this module list as input and then creates a custom UI5 script which contains exactly what is needed. But that's too much manual work because it needs to be applied after every UI5 update. So we also built a server-side mechanism controlled with URL parameter, which creates such an optimized UI5 file on the fly. This one is only usable on Java servers, so it's again not a general solution.

I believe the solution is a small build step (like you proposed), but not based on file imports in HTML, but on dependency declarations in the files. And we are working on it.

But all of these approaches, including your proposal, still have an issue in big application suites where "exactly what is needed" is either very much in total, or is not even known in advance when content is dynamically loaded. So the problem how to load sub-bundles and then efficiently load missing stuff later is still open.

Regards

Andreas

js2
Product and Topic Expert
Product and Topic Expert
0 Kudos

Yep require.js is exactly what I'd use. Catering for small apps and huge ones is certainly a challenge. Looking through the current sources of the require code I can see a few references to require.js compatibility however I couldn't get it to load a require.js module. So it sounds like you're moving towards compatibility which is great.

There's also the ES6 module format coming to browsers very soon.  😉

what about web components - does that point to a solution. If every control was a web component then the CSS and js is self-contained.

Looking forward to it anyway.... Using gulp or grunt would be great as allot of web developers are familiar with those tools...

regards.

AndreasKunz
Advisor
Advisor
0 Kudos


> you're moving towards compatibility

Yes.

> what about web components - does that point to a solution. If every control was a web component then the CSS and js is self-contained.

We are investigating Web Components, but not so much for performance reasons, but for a new Control structure, better encapsulation and native browser support and more developer-friendly usage.

Code size or request count is hardly addressed by Web Components and complete self-contained-ness is not necessarily the best - some kind of dependencies are fine.

Regards

Andreas

AxelSchroeder01
Advisor
Advisor
0 Kudos

Hi Andreas,

are there any news on the topic, that I may missed?
With the newest releases from SAPUI5 / OpenUI5 I still get the 404 from Component-preload.js

Regards,

Axel

AndreasKunz
Advisor
Advisor

Hi Axel,

well, this error comes from the attempt to load this optimized file.

Definitely new since my last comment is that you can create this optimized file for your own applications by using the OpenUI5 grunt build (the "openui5_preload" task with "component" options).

If you don't do this, you will continue seeing this error, but it will not affect the application, we will just load the single files instead.

I think you can still get rid of this error by adding the following parameter to the bootstrap script tag:

data-sap-ui-preload=""

But be aware that using the preload will improve the performance of your application. Also see http://scn.sap.com/community/developer-center/front-end/blog/2015/02/18/optimizing-openui5-apps for more details.

Regards

Andreas

zamboni
Explorer
0 Kudos
Thanks Andreas, of course this is not the correct way to handle the error, but your comment helps to hide the error from those not using component-preload.

Answers (4)

Answers (4)

kammaje_cis
Active Contributor

I too have the same issue.

      Documentation/ReleaseNotes – SAPUI5 Wiki (TIP CORE User Interface)   

Here there is a mention about fixing Component-preload.js Since the component control itself is in development (as per documentation) we may see more changes.

js2
Product and Topic Expert
Product and Topic Expert
0 Kudos

Thanks for pointing out the release notes. I can see that in the November release of 1.16.5 it states: "[FIX] Avoid Component preload when Component has been loaded already". I'm testing on the latest 1.16.8 though and still see the requests.

I understand that the component model is marked as experimental; but these have been there since 1.9.2. Actually allot of the "good stuff" in UI5 is marked as "experimental".

😉

Jayakrishnan
Active Participant
0 Kudos

Hi,

                i am working on the SAPUI5 application. As per my application scenario, i have to consume the sap netweaver service and need to populate the data in master and detail page.i have completed the SAPUI5 exercise (10 exercise). so on top of that i am trying to connect with the oData service.

               i added the real service in Component.js file and mentioned the collection name in the master.view.xml. it is working fine. but i am not able to navigate the selected value in the detail page and i do not know where to mention the second service in the code.

/*master.controller page starts*/

  1. jQuery.sap.require("sap.ui.demo.myFiori.util.Formatter");
  2. jQuery.sap.require("sap.ui.demo.myFiori.util.Grouper");
  3. jQuery.sap.require("sap.ui.core.routing.Router");
  4. jQuery.sap.require("sap.ca.scfld.md.controller.ScfldMasterController");

  1. sap.ui.controller("sap.ui.demo.myFiori.view.Master", {

  oView:null,

  oModel:null,

  onInit : function()

  {

  console.log('onInit of master');

  this.oView = this.getView();

  this.oModel = this.oView.getModel();

  },

  handleListSelect : function(evt)

  {

  console.log('calling handleListSelect item');

  var context = evt.getParameter("listItem").getBindingContext();

  console.log('after seting context');

  var url = "/MyFioriUI5/proxy/sap/opu/odata/sap/ZPR_TRACK_SRV;mo/";

  var oModel = new sap.ui.model.odata.ODataModel(url, true, "", "");

  // oView.setModel(oModel);

  console.log('after seting context'+oModel);

  this.nav.to("Detail", context);

  },

  handleListItemPress : function (evt) {

  var context = evt.getSource().getBindingContext();

  this.nav.to("detail", context);

  },

/*master.controller page ends*/

/*detail.controller page starts*/

  1. jQuery.sap.require("sap.ui.demo.myFiori.util.Formatter");
  2. jQuery.sap.require("sap.m.MessageBox");
  3. jQuery.sap.require("sap.m.MessageToast");

  1. jQuery.sap.require("sap.ca.scfld.md.controller.BaseDetailController");

  1. sap.ui.controller("sap.ui.demo.myFiori.view.Detail", {

  

    onBeforeRendering : function() {

    console.log('in detail page');

  

this.byId("SupplierForm").bindElement("BusinessPartner");

          

    },

    handleNavButtonPress : function()

    {

    console.Log('in detail page1');

    }

});

/*detail .controller page ends*/

/*Component.js page starts*/

  1. jQuery.sap.declare("sap.ui.demo.myFiori.Component");
  2. jQuery.sap.require("sap.ca.scfld.md.ComponentBase");

  1. sap.ui.core.UIComponent.extend("sap.ui.demo.myFiori.Component", {

  metadata: sap.ca.scfld.md.ComponentBase.createMetaData(

  "MD", {

  "name" : "Purchase Requisition",

  "version" : "1.0.0",

  "library" : "sap.ui.demo.myFiori",

  "dependencies" : {

  "libs" : [ "sap.m", "sap.me" ],

  "components" : []

  },

  "config" : {

  "resourceBundle" : "i18n/messageBundle.properties",

  "titleResource" : "app.Identity",

  "icon" : "sap-icon://Fiori2/F0402",

  "favIcon" : "./resources/sap/ca/ui/themes/base/img/favicon/Approve_Purchase_Orders.ico",

  "homeScreenIconPhone" : "./resources/sap/ca/ui/themes/base/img/launchicon/Approve_Purchase_Orders/57_iPhone_Desktop_Launch.png",

  "homeScreenIconPhone@2" : "./resources/sap/ca/ui/themes/base/img/launchicon/Approve_Purchase_Orders/114_iPhone-Retina_Web_Clip.png",

  "homeScreenIconTablet" : "./resources/sap/ca/ui/themes/base/img/launchicon/Approve_Purchase_Orders/72_iPad_Desktop_Launch.png",

  "homeScreenIconTablet@2" : "./resources/sap/ca/ui/themes/base/img/launchicon/Approve_Purchase_Orders/144_iPad_Retina_Web_Clip.png"

  },

  masterPageRoutes : {

  "master" : {

  "pattern" : "GET_ALL_PRSet",

  "view" : "sap.ui.demo.myFiori.view.Master"

  }

  },

  detailPageRoutes : {

  "detail" : {

  "pattern" : "GET_PR_DetailsSet/{contextPath}",

  "view" : "sap.ui.demo.myFiori.view.Detail"

  },

  "noData" : {

  "pattern" : "noData",

  "view" : "empty",

  }

  }

  }),

  createContent : function() {

  // create root view

  var oView = sap.ui.view({

  id : "app",

  viewName : "sap.ui.demo.myFiori.view.App",

  type : "JS",

  viewData : {

  component : this

  }

  });

  // Using OData model to connect against a real service

  var url = "/MyFioriUI5/proxy/sap/opu/odata/sap/ZPR_TRACK_SRV;mo/";

  var oModel = new sap.ui.model.odata.ODataModel(url, true, "", "");

  oView.setModel(oModel);

  // set i18n model

  var i18nModel = new sap.ui.model.resource.ResourceModel({

  bundleUrl : "i18n/messageBundle.properties"

  });

  oView.setModel(i18nModel, "i18n");

  // set device model

  var deviceModel = new sap.ui.model.json.JSONModel({

  isPhone : jQuery.device.is.phone,

  isNoPhone : !jQuery.device.is.phone,

  listMode : (jQuery.device.is.phone) ? "None" : "SingleSelectMaster",

  listItemType : (jQuery.device.is.phone) ? "Active" : "Inactive"

  });

  deviceModel.setDefaultBindingMode("OneWay");

  oView.setModel(deviceModel, "device");

  // Using a local model for offline development

// var oModel = new sap.ui.model.json.JSONModel("model/mock.json");

// oView.setModel(oModel);

  // done

  return oView;

  }

});

/*Component .js page ends*/

 

});

Thank you,

Regards,

JK

Former Member
0 Kudos

HI Gurus,

I am getting the same error Please help.

launchdashboard is my initial view

component.js

------------------------------------------

jQuery.sap.declare("ZGreenfield.Component");

sap.ui.core.UIComponent.extend("ZGreenfield.Component", {

  createContent : function() {

  // create root view

  var oView = sap.ui.view({

  id : "App",

  viewName : "ZGreenfield/greenfield_refinery.launchdashboard",

  type : "JS",

  viewData : { component : this }

  });

// // Using OData model to connect against a real service

// var url = "/proxy/http/<server>:<port>/sap/opu/odata/sap/ZGWSAMPLE_SRV/";

// var oModel = new sap.ui.model.odata.ODataModel(url, true, "<user>", "<password>");

// oView.setModel(oModel);

  // Using a local model for offline development

  var oModel = new sap.ui.model.json.JSONModel("jsonFiles");

  oView.setModel(oModel);

  // done

  return oView;

  }

});

--------------------------------------------

index.html

----------------------------------------------

<!DOCTYPE HTML>

<html>

  <head>

  <meta http-equiv="X-UA-Compatible" content="IE=edge">

  <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>  

  <script

  id="sap-ui-bootstrap"

  src="resources/sap-ui-core.js"

  data-sap-ui-theme="sap_platinum"

  data-sap-ui-libs="sap.ui.commons,sap.ui.table,sap.suite.ui.commons,sap.viz"

  data-sap-ui-resourceroots='{

  "ZGreenfield": "./"

  }' >

  </script>

  <script>

  new sap.ui.core.ComponentContainer({

  name : "ZGreenfield"

  }).placeAt("content");

  </script>

  

  </head>

  <body class="sapUiBody" role="application">

  <div id="content">

  </div>

  </body> 

</html>

-----------------------------------------------

Many Thanks

Pandu

Former Member
0 Kudos

I just resolved this issue, by adding a new file Component-preload.js in the app directory, with following contents:


jQuery.sap.declare("sap.ui.demo.myFiori.Component-preload");

I think it is a nice idea to have this new file so that we can add a piece of code (hook) before loading the whole component.

AndreasKunz
Advisor
Advisor
0 Kudos

Hi,

this file is not meant to be loaded "before" a Component, but it is supposed to contain the entire application code, including all Views, Controllers, etc. within ONE file. (to reduce requsts)

The format is the same (or similar) as the library-preload file, hence the name. "Preload" because all resources are loaded in advance and then parsed on demand.

See my top-level response for more details.

Regards

Andreas