If a Web app seems to have performance issues, finding out what's causing this can be both a time-consuming and nerve-consuming task. To help you avoid and maybe already solve performance issues in your app, here are some good practices we've discovered while dealing with OpenUI5 apps.
When it comes to performance, it's often the case that an app is immediately considered to be slow. But this is only half of the truth. Sure, the app is what can be seen, but what is actually the app? It is the sum of its coding, retrieved and executed in a specific environment.
For OpenUI5 apps, we basically talk about JavaScript files sent to a client by a server and interpreted by the browser. So it's not only the coding of the app the can cause a slow performance. In many cases, it turns out that the configuration is wrong, for example. Slow networks or servers may also have a heavy impact on the performance of a Web app. Let's have a look at the most common issues.
#!text/html<script id="sap-ui-bootstrap" src="openui5/resources/sap-ui-core.js" data-sap-ui-libs="sap.m" data-sap-ui-theme="sap_bluecrystal" data-sap-ui-bindingSyntax="complex" data-sap-ui-compatVersion="edge" data-sap-ui-preload="async" data-sap-ui-resourceroots='{ "your.app": "yourDir/" }'>
For more information on bootstrap attributes, see Bootstrapping: Loading and Initializing.
The most important setting here is data-sap-ui-preload="async". This enables the runtime to load the modules for all declared libraries asynchronously in the background. This reduces the amount of requests sent by the client that could block each other.
Don't forget to implement the asynchronous behavior in the init event of the core as well, as shown in the following code snippet:
#!text/html<script>
sap.ui.getCore().attachInit(function() {
sap.ui.require([
"sap/ui/core/ComponentContainer"
], function(ComponentContainer) {
sap.ui.component({
async: true,
name: "your.component"
}).then(function(yourComponent) {
new ComponentContainer({
component: yourComponent
}).placeAt("content");
});
});
});
</script>
This does not apply for apps that have a descriptor file. In this case, only direct dependencies should be listed. For more information, see Descriptor for Applications, Components, and Libraries.
Synchronous requests that block each other
In this case use the data-sap-ui-preload="async" setting in the bootstrap.
Amount of requests is too big
For OpenUI5 apps that use grunt as a Web server, you can use the openui5_preload task to bundle and minimize all relevant files of a component. For more information, see Optimizing OpenUI5/SAPUI5 Apps in the SAPUI5 Developer Center on SAP SCN. This task creates a Component-preload file.
If you're using SAP Web IDE, refer to Application Build in the SAP Web IDE documentation.
Use non-blocking view loading as described here: Instantiating Views
If you make use of data binding with an OData service as a back end, you may also consider switching your OData model to our more modern V2 OData model. For more information, see OData V2 Model
Make use of asynchronous module loading (AMD style) for custom controls or other scripts. Although it is only supported by the preload, it will help us in future to enable asynchronous loading of individual modules combined with the usage of HTTP/2 or AMD-based packagers. It also ensures proper dependency tracking between modules.
Writing AMD modules is only half the story. You only need to avoid access to OpenUI5 classes via global names. Do not use new sap.m.Button(), but require the Button and call the constructor via the local AMD reference. For more information, see the API Reference for sap.ui.define in the Demo Kit.
Avoid the usage of setTimeout() calls with values greater than 0. This usually indicates an anti-pattern in application code that is used as workaround and should be avoided. (See also JavaScript Code Issues: Don't use timeouts.)
Don't use visibility for lazy instantiation. (See Performance Issues: Don't use visibility for lazy instantiation.)