【问题标题】:How to find loading bottleneck of a slow-loading SAPUI5 app如何找到加载缓慢的 SAPUI5 应用程序的加载瓶颈
【发布时间】:2020-10-21 18:27:50
【问题描述】:

我正在构建一个自定义 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 已弃用,因为它会对最终用户的体验产生不利影响。如需更多帮助,请查看https://xhr.spec.whatwg.org/。 [syncXHRFix-dbg.js:211:15]

我的 index.html 和 manifest.json 的代码 sn-ps

<!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"
    }
}

我的网络标签的屏幕截图

【问题讨论】:

    标签: javascript xmlhttprequest sapui5


    【解决方案1】:

    正如“网络”选项卡所示,有许多模块按顺序加载,其中许多模块甚至通过同步 XHR 加载。最重要的任务是尽可能减少同步 XHR。

    1. 我在manifest.json 中看到只声明了少数库。但是,根据“网络”选项卡,该应用程序使用来自其他库的控件,这些控件未在 dependencies 中声明。
      所以应该是:

      "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": {}
          },
      

      其他库传递地需要某些库(例如,sap.ui.table 需要 sap.ui.unified)。src 如果该库未直接使用,则可以添加 "sap.ui.unified": { lazy: true } .

    2. 预先异步预加载通常通过loadSyncXHR加载的第三方模块。

      如果您检查“网络”选项卡中的 Initiator 列,您可以检测到更多通过同步 XHR 加载的模块。将这些模块添加到 data-sap-ui-modules 应该避免它:

      <script id="sap-ui-bootstrap"
        data-sap-ui-modules="sap/ui/thirdparty/datajs,sap/ui/thirdparty/require"
        ...>
      

      v2.ODataModel 需要 sap/ui/thirdparty/datajssap.viz 库的 sap/ui/thirdparty/require 模块。这两个模块通常通过loadSyncXHR 获取。上面的 sn -p 修复了它。您可能会发现更多这样的模块。

    总的来说,以上几点应该已经显着改善了初始加载时间。如需更多性能指南,请访问Performance Checklist


    其他需要考虑的事项

    I18n

    为了减少请求的数量考虑完全放弃 i18n 支持,如果应用只针对说相同语言的特定人群。多次请求 i18n 文本包不仅大小昂贵,而且在加载时还会阻塞其他请求,因为默认情况下它们也是通过同步 XHR 加载的。 一种方法可以异步加载它们并指定应用程序支持的语言环境,但这是另一个主题。

    OData 模型

    如果不需要,请考虑将计数模式设置为 None,因为在后端计算 $count 的成本往往很高。操作模式Client 也获取所有实体。考虑改为延迟加载它们。

    对于所有聚合绑定

    "": {
      "dataSource": "MyV2Source",
      "settings": {
        "defaultOperationMode": "Default",
        "defaultCountMode": "None",
        "defaultBindingMode": "TwoWay",
        "preliminaryContext": true
      },
      "preload": true
    },
    

    关于preliminaryContext:见Optimizing Dependent Bindings

    对于单个聚合绑定

    items: { // e.g.
      path: '/MySet',
      parameters: {
        countMode: 'None',
        operationMode: 'Client' | 'Default' | 'Server' (see API ref)
      }
    }
    

    API 参考:https://openui5.hana.ondemand.com/api/sap.ui.model.odata.v2.ODataListBinding

    UI5 工具

    在部署应用程序之前,通过以下命令构建应用程序应该会大大减少应用程序的大小:

    ui5 build self-contained -a
    

    来自https://github.com/SAP/openui5-sample-app#option-2-self-contained-build

    这目前仅适用于独立应用。

    【讨论】:

    • 非常有趣,我个人从未考虑过为我的聚合绑定排除 countMode。
    • 不错的详细答案,将其加入书签以供将来参考。
    猜你喜欢
    • 2018-07-28
    • 1970-01-01
    • 2010-11-04
    • 2012-05-23
    • 1970-01-01
    • 2019-01-07
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多