如何找到加载缓慢的 SAPUI5 应用程序的加载瓶颈 [英] How to find loading bottleneck of a slow-loading SAPUI5 app
问题描述
我正在构建一个自定义 SAPUI5 应用程序,它由页面标题内容中的七个图表 (sap.viz.ui5.controls.VizFrame
) 组成(嵌套在 sap.suite.ui.commons.ChartContainer
) 和主要内容区域中的网格表 (sap.ui.table.Table
).图表和表格的数据由 OData V2 服务提供,该应用在最新版本 (1.81.0) 上独立运行.
问题是应用加载时间过长.需要 7 到 20 秒.这对于更复杂"的应用程序来说是常见的吗?应用程序?我试图找到瓶颈,但一切看起来都很好.许多网络请求被缓存(它们需要 0 毫秒),但是,它们之间有轻微的延迟,我不明白为什么.此外,尽管我在 index.html
文件中使用了 data-sap-async=true"
,但控制台中还有以下警告:><块引用>
[弃用] 主线程上的同步 XMLHttpRequest 已弃用,因为它对最终用户的体验有不利影响.如需更多帮助,请查看
正如网络"选项卡所示,有许多模块一一依次加载,其中许多甚至通过同步 XHR 加载.最重要的任务是尽可能减少同步 XHR.
我在
manifest.json
中看到只声明了少量库.但是,根据网络选项卡,该应用程序使用来自其他库的控件,这些控件未在dependencies
中声明.
所以应该是:sap.ui5":{依赖关系":{库":{sap.ui.core":{},sap.m":{},sap.ui.table":{},sap.f":{},sap.ui.unified":{},sap.ui.layout":{},sap.viz":{},sap.suite.ui.commons":{}},
一些库被其他库传递需要(例如
sap.ui.table
需要sap.ui.unified
).src 然后您可以添加"sap.ui.unified": { lazy: true }
如果该库没有直接使用.预先异步预加载通常通过
loadSyncXHR
加载的第三方模块.如果您检查 Network 选项卡中的 Initiator 列,您可以检测到更多通过同步 XHR 加载的模块.将这些模块添加到
data-sap-ui-modules
应该避免它:v2.ODataModel
需要sap/ui/thirdparty/datajs
.sap.viz
库的sap/ui/thirdparty/require
模块.这两个模块通常通过loadSyncXHR
获取.上面的代码片段修复了它.您可能会发现更多此类模块.
总的来说,以上几点应该已经显着改善了初始加载时间.如需更多性能指南,请查看性能清单.
其他需要考虑的事项
I18n
为了减少请求数量考虑完全放弃对 i18n 的支持,如果该应用仅针对使用相同语言的特定人群.多次请求i18n 文本包不仅大小昂贵,而且在加载时会阻止其他请求,因为默认情况下它们也是通过同步 XHR 加载的. 有一种方法可以异步加载它们并指定应用支持的区域设置,但这是另一个主题.
OData 模型
如果不需要,请考虑将计数模式设置为 None
,因为 $count
计算在后端往往成本很高.此外,操作模式 Client
获取所有实体.考虑改为延迟加载它们.
对于所有聚合绑定
":{数据源":MyV2Source",设置":{defaultOperationMode":默认",defaultCountMode":无",默认绑定模式":双向",preliminaryContext":真},预加载":真},
关于 API 参考:https:///openui5.hana.ondemand.com/api/sap.ui.model.odata.v2.ODataListBinding 在部署应用程序之前,通过以下命令构建应用程序应该会大大减少应用程序的大小: 来自 https://github.com/SAP/openui5-sample-app#option-2-self-contained-build 这目前仅适用于独立应用. I'm building a custom SAPUI5 app which consists of a seven diagrams ( The problem is the long loading time of the app. It takes between 7 and 20 seconds. Is this common for a "more complex" app? I tried to find the bottleneck but everything looks fine. Many network requests are cached (they take 0ms), however, there is a slight delay in between them and I can't see why. Additionally, there is the following warning in the console, although I'm using the [Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. [syncXHRFix-dbg.js:211:15]
preliminaryContext
:请参阅items: {//例如路径:'/MySet',参数: {计数模式:'无',操作模式:'客户端' |'默认' |服务器"(参见 API 参考)}}
UI5 工具
ui5 build self-contained -a
sap.viz.ui5.controls.VizFrame
) in the page's header content (nested inside a sap.suite.ui.commons.ChartContainer
) and a grid table (sap.ui.table.Table
) in the main content area. The data for the charts and the table is provided by an OData V2 Service and the app is running stand-alone on the latest version (1.81.0).data-sap-async="true"
in my index.html
file:
Code snippets of my index.html and manifest.json
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Loading - Customer Fact Sheet</title>
<script id="sap-ui-bootstrap"
src="resources/sap-ui-core.js"
data-sap-ui-theme="sap_fiori_3"
data-sap-ui-resourceroots='{"com.schott.fiori.customerfactsheet.customerfactsheet-fiori3": "./"}'
data-sap-ui-compatVersion="edge"
data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
data-sap-ui-async="true"
data-sap-ui-frameOptions="trusted">
</script>
<link href="https://www.schott.com/static/assets/gfx/favicon/SCHOTT_16.png" rel="shortcut icon" type="image/png" />
</head>
<body class="sapUiBody">
<div data-sap-ui-component data-name="com.schott.fiori.customerfactsheet.customerfactsheet-fiori3" data-id="container" data-settings='{"id" : "customerfactsheet-fiori3"}'></div>
</body>
</html>
{
"_version": "1.12.0",
"sap.app": {
"id": "com.schott.fiori.customerfactsheet.customerfactsheet-fiori3",
"type": "application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "1.0.0"
},
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"sourceTemplate": {
"id": "servicecatalog.connectivityComponentForManifest",
"version": "0.0.0"
},
"dataSources": {
"YODATA_SD_CFS_MATRIX_SRV": {
"uri": "/sap/opu/odata/sap/YODATA_SD_CFS_MATRIX_SRV/",
"type": "OData",
"settings": {
"localUri": "localService/metadata.xml"
}
}
}
},
"sap.ui": {
"technology": "UI5",
"icons": {
"icon": "",
"favIcon": "",
"phone": "",
"phone@2": "",
"tablet": "",
"tablet@2": ""
},
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
}
},
"sap.ui5": {
"flexEnabled": false,
"rootView": {
"viewName": "com.schott.fiori.customerfactsheet.customerfactsheet-fiori3.view.Main",
"type": "XML",
"async": true,
"id": "Main"
},
"dependencies": {
"minUI5Version": "1.65.6",
"libs": {
"sap.ui.layout": {},
"sap.ui.core": {},
"sap.m": {}
}
},
"contentDensities": {
"compact": true,
"cozy": false
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "com.schott.fiori.customerfactsheet.customerfactsheet-fiori3.i18n.i18n"
}
},
"": {
"type": "sap.ui.model.odata.v2.ODataModel",
"settings": {
"defaultOperationMode": "Client",
"defaultBindingMode": "OneWay",
"defaultCountMode": "Request"
},
"dataSource": "YODATA_SD_CFS_MATRIX_SRV",
"preload": true
}
},
"resources": {
"css": [{
"uri": "css/style.css"
}]
},
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"async": true,
"viewPath": "com.schott.fiori.customerfactsheet.customerfactsheet-fiori3.view",
"controlAggregation": "pages",
"controlId": "app",
"clearControlAggregation": false
},
"routes": [{
"name": "RouteMain",
"pattern": "RouteMain",
"target": ["TargetMain"]
}],
"targets": {
"TargetMain": {
"viewType": "XML",
"transition": "slide",
"clearControlAggregation": false,
"viewId": "Main",
"viewName": "Main"
}
}
}
},
"sap.platform.hcp": {
"uri": "webapp",
"_version": "1.1.0"
}
}
Screenshots of my network tab
As the Network tab shows, there are many modules loading sequentially one by one and many of them even via sync XHR. The most important task is to reduce sync XHRs as much as possible.
I see in the
manifest.json
that only a small number of libraries are declared. According to the Network tab, however, the app uses controls from other libs which aren't declared in thedependencies
.
So it should be:"sap.ui5": { "dependencies": { "libs": { "sap.ui.core": {}, "sap.m": {}, "sap.ui.table": {}, "sap.f": {}, "sap.ui.unified": {}, "sap.ui.layout": {}, "sap.viz": {}, "sap.suite.ui.commons": {} },
Some libs are required by other libs transitively (e.g.
sap.ui.table
requiressap.ui.unified
).src You may then add"sap.ui.unified": { lazy: true }
if that lib is not directly in use.Preload thirdparty modules asynchronously beforehand that are usually loaded via
loadSyncXHR
.If you inspect the Initiator column within the Network tab, you can detect more modules that are loaded via sync XHR. Adding those modules to the
data-sap-ui-modules
should avoid it:<script id="sap-ui-bootstrap" data-sap-ui-modules="sap/ui/thirdparty/datajs,sap/ui/thirdparty/require" ...>
The
sap/ui/thirdparty/datajs
is required byv2.ODataModel
. Thesap/ui/thirdparty/require
module by thesap.viz
library. Both modules are usually fetched vialoadSyncXHR
. The above snippet fixes it. You might find more such modules.
Overall, the above points should should already improve the initial loading time noticeably. For more performance guidelines, go through the Performance Checklist.
Other things to consider
I18n
In order to reduce the number of requests consider to drop the i18n-support altogether if the app targets only a certain group of people speaking the same language. Multiple requests for i18n text bundles are not only costly in size but also blocking other requests while loading as they're also loaded via sync XHRs by default. There is a way to load them asynchronously and also specifying which locales the app supports, but that's for another topic.
OData Model
Consider to set the count mode to None
if not required since $count
calculations tend to be costly in the backend. Also the operation mode Client
fetches all entities. Consider to lazy-load them instead.
For all aggregation bindings
"": {
"dataSource": "MyV2Source",
"settings": {
"defaultOperationMode": "Default",
"defaultCountMode": "None",
"defaultBindingMode": "TwoWay",
"preliminaryContext": true
},
"preload": true
},
About preliminaryContext
: see Optimizing Dependent Bindings.
For a single aggregation binding
items: { // e.g.
path: '/MySet',
parameters: {
countMode: 'None',
operationMode: 'Client' | 'Default' | 'Server' (see API ref)
}
}
API reference: https://openui5.hana.ondemand.com/api/sap.ui.model.odata.v2.ODataListBinding
UI5 tooling
Before deploying the app, building the app via the following command should reduce the application size drastically:
ui5 build self-contained -a
From https://github.com/SAP/openui5-sample-app#option-2-self-contained-build
This is currently applicable to stand-alone apps only.
这篇关于如何找到加载缓慢的 SAPUI5 应用程序的加载瓶颈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!