Files
gh-secondsky-sap-skills-ski…/references/performance-optimization.md
2025-11-30 08:55:36 +08:00

15 KiB

SAPUI5 Performance Optimization

Source: Official SAP SAPUI5 Documentation Documentation: https://github.com/SAP-docs/sapui5/tree/main/docs/05_Developing_Apps Last Updated: 2025-11-21


Core Loading Strategies

1. Asynchronous Loading (Critical)

Always enable asynchronous loading for optimal performance.

Bootstrap Configuration:

<script
    id="sap-ui-bootstrap"
    src="resources/sap-ui-core.js"
    data-sap-ui-async="true"
    data-sap-ui-on-init="module:sap/ui/core/ComponentSupport"
    data-sap-ui-resource-roots='{
        "my.app": "./"
    }'>
</script>

Component Interface:

sap.ui.define([
    "sap/ui/core/UIComponent"
], function(UIComponent) {
    "use strict";

    return UIComponent.extend("my.app.Component", {
        interfaces: ["sap.ui.core.IAsyncContentCreation"],

        metadata: {
            manifest: "json"
        }
    });
});

Benefits:

  • Non-blocking module loading
  • Parallel resource fetching
  • Faster initial load time
  • Better user experience

2. Manifest-First Approach

Configure dependencies in manifest.json instead of bootstrap.

manifest.json:

{
    "sap.ui5": {
        "dependencies": {
            "minUI5Version": "1.120.0",
            "libs": {
                "sap.m": {},
                "sap.ui.core": {},
                "sap.f": {}
            }
        }
    }
}

Benefits:

  • Dependency reuse across contexts
  • Earlier rendering
  • Parallel loading optimization
  • Design-time tool support

3. Lazy Loading Libraries

Load heavy libraries only when needed:

manifest.json:

{
    "sap.ui5": {
        "dependencies": {
            "libs": {
                "sap.m": {},
                "sap.ui.table": {
                    "lazy": true
                }
            }
        }
    }
}

Load Before Use:

sap.ui.require(["sap/ui/core/Lib"], function(Library) {
    Library.load({ name: "sap.ui.table" }).then(function() {
        // Library loaded, now create table
    });
});

Resource Optimization

1. CDN Distribution

Load SAPUI5 from CDN for better performance:

<script
    src="[https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"](https://sapui5.hana.ondemand.com/resources/sap-ui-core.js")
    data-sap-ui-async="true">
</script>

Benefits:

  • Global CDN distribution (AKAMAI)
  • Reduced latency
  • Caching across applications
  • No server load

2. Component Preload

Enable component preload to bundle resources:

Automatic (UI5 Tooling):

ui5 build

Creates Component-preload.js containing:

  • All views
  • All controllers
  • All fragments
  • manifest.json
  • i18n files

Load Component Preload:

{
    "sap.ui5": {
        "dependencies": {
            "components": {
                "my.other.component": {
                    "lazy": false  // Preload enabled by default
                }
            }
        }
    }
}

3. Library Preloads

Ensure library preloads are enabled (default):

Check Configuration:

// Preloads enabled by default
// Don't set data-sap-ui-preload="sync" (synchronous loading)

Verify Preload Loading:

  • Open Network tab in browser
  • Look for library-preload.js files
  • Should see ONE request per library, not many

4. i18n Configuration

Prevent 404 errors for missing language files:

manifest.json:

{
    "sap.ui5": {
        "models": {
            "i18n": {
                "type": "sap.ui.model.resource.ResourceModel",
                "settings": {
                    "bundleName": "my.app.i18n.i18n",
                    "supportedLocales": ["en", "de", "fr"],
                    "fallbackLocale": "en"
                }
            }
        }
    }
}

File Structure:

i18n/
├── i18n.properties          (fallback)
├── i18n_en.properties       (English)
├── i18n_de.properties       (German)
└── i18n_fr.properties       (French)

Code Optimization

1. Replace Deprecated jQuery

Migrate from deprecated jquery.sap.* modules:

Before (deprecated):

jQuery.sap.require("sap.m.MessageBox");
jQuery.sap.delayedCall(100, this, function() {});

After (modern):

sap.ui.require(["sap/m/MessageBox"], function(MessageBox) {});

setTimeout(function() {}, 100);

Migration Guide:

  • jQuery.sap.delayedCallsetTimeout
  • jQuery.sap.logsap/base/Log
  • jQuery.sap.uidsap/base/util/uid
  • jQuery.sap.getUriParameterssap/base/util/UriParameters

2. Asynchronous Factories

Use async variants for better performance:

Components:

// Old (sync)
var oComponent = sap.ui.component({
    name: "my.app"
});

// New (async)
sap.ui.require(["sap/ui/core/Component"], function(Component) {
    Component.create({
        name: "my.app",
        manifest: true
    }).then(function(oComponent) {
        // Component ready
    });
});

Views:

// Old (sync)
var oView = sap.ui.view({
    viewName: "my.app.view.Main",
    type: "XML"
});

// New (async)
sap.ui.require(["sap/ui/core/mvc/XMLView"], function(XMLView) {
    XMLView.create({
        viewName: "my.app.view.Main"
    }).then(function(oView) {
        // View ready
    });
});

Controllers:

// Controllers loaded automatically with views (async)

Resource Bundles:

// Old (sync)
var oBundle = jQuery.sap.resources({
    url: "i18n/i18n.properties"
});

// New (async)
sap.ui.require(["sap/base/i18n/ResourceBundle"], function(ResourceBundle) {
    ResourceBundle.create({
        url: "i18n/i18n.properties",
        async: true
    }).then(function(oBundle) {
        // Bundle ready
    });
});

Data Handling

1. OData Model Preload

Enable metadata preloading:

manifest.json:

{
    "sap.ui5": {
        "models": {
            "": {
                "dataSource": "mainService",
                "preload": true,
                "settings": {
                    "defaultBindingMode": "TwoWay"
                }
            }
        }
    }
}

Benefits:

  • Metadata loads during component init
  • Faster first data request
  • No metadata loading delay

2. Use $select for OData

Fetch only needed properties:

Without $select (bad):

// Fetches ALL properties
this.getView().bindElement("/Products('123')");

With $select (good):

// Fetches only specified properties
this.getView().bindElement({
    path: "/Products('123')",
    parameters: {
        select: "ProductID,Name,Price,Category"
    }
});

In List/Table:

<Table
    items="{
        path: '/Products',
        parameters: {
            select: 'ProductID,Name,Price',
            expand: 'Category'
        }
    }">

Benefits:

  • Smaller payload
  • Faster backend queries
  • Reduced network transfer
  • Better performance

3. OData V4 Migration

Prefer OData V4 over V2:

manifest.json:

{
    "sap.app": {
        "dataSources": {
            "mainService": {
                "uri": "/odata/v4/catalog/",
                "type": "OData",
                "settings": {
                    "odataVersion": "4.0"
                }
            }
        }
    },
    "sap.ui5": {
        "models": {
            "": {
                "dataSource": "mainService",
                "settings": {
                    "synchronizationMode": "None",
                    "operationMode": "Server",
                    "autoExpandSelect": true
                }
            }
        }
    }
}

Benefits:

  • Better performance
  • Server-side operations
  • Automatic $expand and $select
  • Modern features

4. Batch Requests

Combine multiple requests:

OData V2:

var oModel = this.getView().getModel();

oModel.setUseBatch(true);
oModel.setDeferredGroups(["changes"]);

// Add to batch
oModel.create("/Products", oData1, { groupId: "changes" });
oModel.create("/Products", oData2, { groupId: "changes" });
oModel.update("/Products('1')", oData3, { groupId: "changes" });

// Submit batch
oModel.submitChanges({
    groupId: "changes",
    success: function() {
        MessageToast.show("All changes saved");
    }
});

Benefits:

  • Single HTTP request
  • Reduced network overhead
  • Better performance
  • Atomic operations

5. Metadata Caching

Enable metadata caching for ABAP backends:

Automatic: SAPUI5 uses cache tokens automatically

Check Network:

  • Look for sap-context-token parameter
  • Metadata should load from cache on subsequent visits

UI Control Performance

1. Table Selection

Choose appropriate table control:

sap.m.Table (Mobile/Responsive):

  • Good for: < 100 rows
  • Keeps all rows in DOM
  • Better for responsive layouts
  • Growing/scrolling support

sap.ui.table.Table (Grid/Analytical):

  • Good for: 100+ rows
  • Virtual scrolling (only visible rows in DOM)
  • High performance for large datasets
  • Fixed column layout

Example:

<!-- For < 100 rows -->
<m:Table
    items="{/Products}"
    growing="true"
    growingThreshold="20">
</m:Table>

<!-- For 100+ rows -->
<table:Table
    rows="{/Products}"
    visibleRowCount="20"
    threshold="50">
</table:Table>

2. Reduce Control Complexity

Minimize controls in repeated aggregations:

Bad (heavy):

<items>
    <ColumnListItem>
        <cells>
            <VBox>
                <Text text="{Name}"/>
                <Text text="{Description}"/>
                <HBox>
                    <Button text="Edit"/>
                    <Button text="Delete"/>
                </HBox>
            </VBox>
        </cells>
    </ColumnListItem>
</items>

Good (light):

<items>
    <ColumnListItem>
        <cells>
            <ObjectIdentifier
                title="{Name}"
                text="{Description}"/>
        </cells>
    </ColumnListItem>
</items>

3. Remove Hidden Columns

Don't hide columns with visible="false" in tables - remove them entirely:

Bad:

<columns>
    <Column visible="false">
        <Text text="Hidden Column"/>
    </Column>
</columns>

Good:

// Add/remove columns dynamically based on device
if (sap.ui.Device.system.desktop) {
    oTable.addColumn(oColumn);
}

Network & Debugging

1. Network Inspection

Monitor browser Network tab:

Check for:

  • Synchronous blocking requests (waterfall shows blocks)
  • Excessive request count (> 50 for initial load)
  • Large response sizes
  • Slow backend responses
  • 404 errors (missing files)
  • Duplicate requests

Tools:

  • Chrome DevTools Network tab
  • Firefox Network Monitor
  • UI5 Inspector extension

2. Avoid Debug Mode

Never use debug mode in production:

Development:

[http://localhost:8080/index.html?sap-ui-debug=true](http://localhost:8080/index.html?sap-ui-debug=true)

Production (don't do this):

[http://myapp.com/index.html?sap-ui-debug=true](http://myapp.com/index.html?sap-ui-debug=true)

Why: Debug mode loads individual source files instead of preloads.


3. Performance Measurement

Use built-in performance tools:

Enable Performance Trace:

sap.ui.require(["sap/ui/performance/Measurement"], function(Measurement) {
    Measurement.setActive(true);

    // Custom measurements
    Measurement.start("myOperation");
    // ... operation ...
    Measurement.end("myOperation");

    // Get results
    var aMeasurements = Measurement.getAllMeasurements();
    console.table(aMeasurements);
});

UI5 Inspector:

  • Open UI5 Inspector extension
  • Go to Performance tab
  • See loading times, rendering times, etc.

Anti-Patterns to Avoid

1. setTimeout with Delays

Bad:

setTimeout(function() {
    this.doSomething();
}.bind(this), 100);  // 100ms delay

Good:

// Do immediately when possible
this.doSomething();

// Or use events
this.attachEventOnce("dataReceived", this.doSomething, this);

2. Visibility-Based Lazy Loading

Bad:

onAfterRendering: function() {
    if (this.byId("panel").getVisible()) {
        this.loadData();
    }
}

Good:

// Use routing or explicit user actions
onButtonPress: function() {
    this.loadData();
}

3. Blocking Rendering

Bad:

onInit: function() {
    // Blocks rendering until data loaded
    var oData = this.loadDataSync();  // Synchronous
    this.getView().setModel(new JSONModel(oData));
}

Good:

onInit: function() {
    // Show loading, load async
    this.getView().setBusy(true);

    this.loadDataAsync().then(function(oData) {
        this.getView().setModel(new JSONModel(oData));
        this.getView().setBusy(false);
    }.bind(this));
}

4. Excessive Dependencies

Bad:

sap.ui.define([
    "sap/m/Button",
    "sap/m/Input",
    "sap/m/Text",
    // ... 50 more controls
], function(Button, Input, Text, ...) {
    // Only using 5 of them
});

Good:

sap.ui.define([
    "sap/m/Button",
    "sap/m/Input"
], function(Button, Input) {
    // Only what's needed
});

Performance Checklist

Loading

  • Async loading enabled (data-sap-ui-async="true")
  • Component implements IAsyncContentCreation
  • Dependencies in manifest.json
  • Heavy libraries lazy loaded
  • Component preload generated
  • CDN used for SAPUI5

Data

  • OData metadata preload enabled
  • $select used for queries
  • Batch requests for multiple operations
  • OData V4 used when possible
  • Metadata caching working

UI

  • Appropriate table control chosen
  • Virtual scrolling for large lists
  • Control complexity minimized
  • No hidden columns in tables
  • Growing lists for mobile

Code

  • No deprecated jQuery.sap modules
  • Async factories used
  • No setTimeout delays
  • No visibility-based lazy loading
  • No blocking rendering

Network

  • < 50 requests for initial load
  • No 404 errors
  • No duplicate requests
  • Debug mode disabled
  • Preloads loading correctly

Performance Metrics

Target Initial Load Time:

  • 3G Network: < 5 seconds
  • LTE Network: < 2 seconds
  • Desktop/WiFi: < 1 second

Measure Performance:

# Lighthouse audit
lighthouse [https://myapp.com](https://myapp.com) --view

# WebPageTest
# Visit [https://www.webpagetest.org/](https://www.webpagetest.org/)

Official Documentation


Note: This document covers performance optimization for SAPUI5 applications. Implement these practices for production-ready, high-performance applications.