Как найти узкое место при загрузке медленно загружаемого приложения SAPUI5

#javascript #xmlhttprequest #sapui5

#javascript #xmlhttprequest #sapui5

Вопрос:

Я создаю пользовательское приложение SAPUI5, которое состоит из семи диаграмм ( sap.viz.ui5.controls.VizFrame ) в содержимом заголовка страницы (вложенных внутри sap.suite.ui.commons.ChartContainer ) и таблицы сетки ( sap.ui.table.Table ) в основной области содержимого. Данные для диаграмм и таблицы предоставляются службой OData V2, и приложение работает автономно в последней версии (1.81.0).

Проблема заключается в длительном времени загрузки приложения. Это занимает от 7 до 20 секунд. Является ли это обычным для «более сложного» приложения? Я пытался найти узкое место, но все выглядит нормально. Многие сетевые запросы кэшируются (они занимают 0 мс), однако между ними есть небольшая задержка, и я не понимаю, почему. Кроме того, в консоли отображается следующее предупреждение, хотя я использую data-sap-async="true" в своем index.html файле:

[Устаревание] Синхронный запрос XMLHttpRequest в основном потоке устарел из-за его пагубных последствий для работы конечного пользователя. Для получения дополнительной помощи проверьте https://xhr.spec.whatwg.org /. [syncXHRFix-dbg.js:211:15]

Фрагменты кода моего index.html и 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"
    }
}
  

Скриншоты вкладки «Моя сеть»

Сеть 1

Сеть 2

Сеть 3

Сеть 4

Ответ №1:

Как видно на вкладке Сеть, существует множество модулей, загружающихся последовательно один за другим, и многие из них даже через sync 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 .

    Если вы проверите столбец Инициатор на вкладке Сеть, вы можете обнаружить больше модулей, которые загружаются через sync XHR. Добавление этих модулей в data-sap-ui-modules должно избежать этого:

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

    sap/ui/thirdparty/datajs Требуется v2.ODataModel . sap/ui/thirdparty/require Модуль от sap.viz библиотеки. Оба модуля обычно извлекаются через loadSyncXHR . Приведенный выше фрагмент исправляет это. Возможно, вы найдете больше таких модулей.

В целом, вышеуказанные пункты уже должны заметно улучшить время начальной загрузки. Для получения дополнительных рекомендаций по производительности ознакомьтесь с контрольным списком производительности.


Другие вещи, которые следует учитывать

I18n

Чтобы уменьшить количество запросов, рассмотрите возможность полного отказа от поддержки i18n, если приложение предназначено только для определенной группы людей, говорящих на одном языке. Множественные запросы для текстовых пакетов i18n не только дорого обходятся по размеру, но и блокируют другие запросы во время загрузки, поскольку они также загружаются через sync XHRS по умолчанию. Есть способ загружать их асинхронно, а также указывать, какие локали поддерживает приложение, но это для другой темы.

Модель OData

Подумайте о том, чтобы установить режим подсчета на, None если это не требуется, поскольку $count вычисления, как правило, являются дорогостоящими в серверной части. Также режим работы Client извлекает все объекты. Подумайте о том, чтобы вместо этого загружать их лениво.

Для всех привязок агрегации

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

О preliminaryContext : смотрите раздел Оптимизация зависимых привязок.

Для одной привязки агрегации

 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

В настоящее время это применимо только к автономным приложениям.

Комментарии:

1. очень интересно, я лично никогда не рассматривал возможность исключения countMode для моих привязок агрегации.

2. Хороший подробный ответ, собираюсь добавить его в закладки для дальнейшего использования.