Skip to Content

As UI5 has grown over the years, the size of the jQuery.sap.* modules have also increased quite a bit and applications are still bound to use global variables to access the provided functionality. In our effort to decrease the UI5 footprint, as well as decouple our framework and applications from the global namespace, we split the original jQuery.sap.* modules into smaller ones to reduce complexity and side effects.

Furthermore, we have updated our browser and platform support (Browser and Platform Support). With this, several APIs became obsolete and can be replaced by native browser APIs which were not available in older browser versions. The modules are introduced with SAPUI5 version 1.58 (UI5 Evolution). With the introduction of the new UI5 core modules, the original jQuery.sap.* modules are now deprecated.

With this blog post we want to give you a brief outlook on what’s new and how you can migrate your applications to the current state of UI5 development.

 

Current State

As shown in the picture, we distinguish between three different application types:

  • Legacy: Older applications still using global variables to access UI5 features, e.g. jQuery.sap.byId().
  • UI5 Classic: Applications using sap.ui.define/sap.ui.require with correctly maintained dependencies to jQuery.sap.* modules
  • UI5 Evolution: Applications using the asynchronous ui5loader together with the new smaller UI5 Core modules

To keep the legacy applications stable, we also introduced a “Stubbing Layer”(see Legacy in the picture above) which provides the lazy loading of legacy modules in order to stay backward compatible. The stubbing layer only provides the legacy jQuery.sap.* API namespaces. The actual implementation is then loaded synchronously on demand.

This stubbing mechanism is provided via a new compatibility module jQuery.sap.stubs. This module will be loaded with the UI5 core by default, so you don’t have to do anything to keep your application stable and compatible.

Important

Though the stubbing mechanism will keep existing applications running, we highly advice you to migrate your application away from the jQuery.sap.* namespace.

Holding on to the jQuery.sap.* namespace will be detrimental to the performance of your application, since every access to jQuery.sap.* functionality will trigger a synchronous XHR blocking JavaScripts main thread and thus the UI.

See also the MDN Web Docs on Synchronous and Asynchronous Requests for a good overview of the topic.

With that said, let’s have a look on how you can evolve your app so you won’t have any issues with unwanted synchronous XHRs.

There are basically three steps you have to perform.

1. Always declare the full dependencies

You should always fully declare the dependencies for your modules, so you can make sure that no synchronous requests are sent. By migrating your modules to AMD-syntax with a complete declaration of dependencies, you can also benefit from state of the art resource bundling (UI5 Build and Development Tooling).

If you need a module during the initialization (respectively the constructor call) of a class, declare the dependency statically in your sap.ui.define call. Dependencies which are not necessarily required during initialization can be declared asynchronously later on by using sap.ui.require. In the snippet below, you see a sample using both functions. Additional examples can be found in the above linked API documentation.

New API
sap.ui.define(["sap/base/Log", "sap/ui/core/Control"], function(Log, Control) {
    return Control.extend("my.Control", {
        doThings: function() {
            Log.info("Tada!");
        },
        lazyStuff: function() {
            Log.info("Async API using sap.ui.require(...).");
            return new Promise(function(res, rej) {
                sap.ui.require(["some/other/module"], function() {
                    res();
                });
            });
        }
    });
});

 

2. Migrate to jQuery.sap.* replacements

In most cases, you should be able to replace the old jQuery.sap.* call via search and replace and just include the dependency to the new module. In other cases, we don’t have a new module, but leverage the native browser API, so that these calls can also be replaced quite easily. Only in a few cases, you may need to change your code a bit more.

The UI5 developer guide provides a comprehensive list of all legacy API jQuery.sap.* API calls and their new replacements. You can find it here.

For module loading in general, you can find further helpful details and best practices for loading modules and dependencies here.

For example, you can replace “jQuery.sap.log” …

Old API
jQuery.sap.log.info("Do not use jQuery.sap.* APIs anymore.");

… with the “sap/base/Log” module:

New API
sap.ui.require(["sap/base/Log"], function(Log) {
    Log.info("Use new APIs instead!");
});

 

3. Migrate to legacy factories replacements

In addition to the split of the jQuery.sap.* modules, the factory functions inside the sap.ui.* namespace have also been refactored. We now provide fully asynchronous APIs on top.

The old APIs are of course still available for compatibility reasons, but are also deprecated. You can find the complete overview of all legacy factory replacements here.

So, for example, instead of using “sap.ui.view()” …

Old API
var oView = sap.ui.view({
    viewName: "my.View",
    type: "XML"
});

… rather use “sap/ui/core/mvc/View.create”:

New API
sap.ui.require(['sap/ui/core/mvc/View'], function(View){
    View.create({
        viewName: "my.View",
        type: "XML"
    }).then(function(oView) { ... });
});

Oh and by the way, instead of using View.create() with type “XML” you could also simply use the typed factory function on the XMLView class:

sap.ui.require(['sap/ui/core/mvc/XMLView'], function(XMLView){
    XMLView.create({
        viewName: "my.View",
    }).then(function(oXmlView) { ... });
});

Pro-Tip: The other view types also have these convenience factory functions.

 

Let’s move forward

With this blog post we have given you a short overview of the current state of UI5 development and a first primer on how to migrate your application code to a more robust state.

Using sap.ui.require and sap.ui.define your application become completely independent from the global namespace and closer to be fully asynchronous.

Further, with the split of the legacy jQuery.sap.* modules we are getting closer to our goal of having a fully modular framework. Applications benefit from the new modules due to a smaller JavaScript footprint, which is beneficial for the startup-performance. Simply put, stuff that is not needed will not be loaded anymore.

Finally we gave you a short example on our new factory functions, which feature a fully asynchronous behavior.

Now it’s your turn! 🙂

 

Previous post: UI5ers Buzz #37

Author

Thorsten is a UI5 Core Developer, gaming enthusiast, minimalist, and highly addicted to High Definition Entertainment Systems. He is currently focusing on improving the UI5 code base to make it a better place for applications.
Tommy is a UI5 Core Developer, food photographer, home cinema enthusiast, and always owns the latest consumer electronic gadgets. In his daily work, he tries to leave our code base in a better shape than he has found it.
Tobias is a Coding Warrior and lovely Dad of a future UI5 Developer. Oh, and by the way, he is saving the world by riding the bike to work every day.

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

Leave a Reply