How to avoid “Synchronous XMLHttpRequest on the main thread” warning in UI5?

此生再无相见时 提交于 2020-12-11 00:57:36

问题


I'm staring my UI5 with the following bootstrapping in index.js:

sap.ui.define([
    "sap/m/Shell",
    "sap/ui/core/ComponentContainer"
], (Core, Shell, ComponentContainer) => {
    "use strict";

    new Shell("", {
        app: new ComponentContainer("", {
            height: "100%",
            name: "webapp"
        }),
        appWidthLimited: false
    }).placeAt("content");
});

According to the UI5 documentation:

Static dependencies are loaded in the dependency declaration array of the sap.ui.define call. These dependencies are always loaded in advance before executing the defined module.

Do I understand it correctly that in such case the modules will be always loaded in a synchronous way and there is no real way to avoid the «Synchronous XMLHttpRequest on the main thread» warning?

Can I, perhaps, just wrap new sap.m.Shell(sId?, mSettings?) with async/await?

Update #1:

I've checked the loading with ?sap-ui-xx-nosync=warn and got the following results:

enter image description here

For some reason i18n/i18n_en.properties is loaded synchronously. The only place where I'm accessing the i18n is:

const oBundle = myI18nModel.getResourceBundle();

But following the documentation, I could not grasp why myI18nModel.getResourceBundle() leads to the synchronous loading.

Update #2:

After a deep exploration of no sync XHR sample, I found out the reason for the sync XHR warning. That was "description": "{{appDescription}}" and "title": "{{appTitle}}" in manifest.json which is explicitly noted:

"title": "Here the i18n bundles can't be loaded with 'async: true' yet!",
"description": "Same here. Hence, no 'i18n' in this 'sap.app' section!"

After replacing it with a static values the warning is gone.


回答1:


Early development of UI5 was heavily based on synchronous XHRs. Legacy applications or some outdated documentation topics might still refer to APIs that have either the asynchronous option disabled by default or no async option at all such as: sap.ui.controller, sap.ui.component, sap.ui.*fragment, sap.ui.*view, jQuery.sap.require, sap.ui.requireSync, jQuery.sap.sjax, and the constructor function of the ComponentContainer as mentioned in the question.

In order to reduce the number of sync XHR calls:

  1. Follow the documented guidelines:

    • Performance Checklist
    • Is Your Application Ready for Asynchronous Loading?

    Particularly when bootstrapping, use the data-sap-ui-async="true" option, and, if the app has a Component.js, use the declarative sap/ui/core/ComponentSupport module in data-sap-ui-oninit instead of instantiating sap.ui.core.ComponentContainer manually. For example:

    <head>
      &lt!-- ... -->
      <script id="sap-ui-bootstrap" ...
        data-sap-ui-async="true"
        data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
      ></script>
    </head>
    <body id="content" class="sapUiBody">
      <div data-sap-ui-component
        data-id="rootComponentContainer"
        data-name="demo"
        data-settings='{ "id": "rootComponent" }'
        ...
      ></div>
    </body>

    This automatically creates a ComponentContainer, pushes it to the DOM, and loads the Component.js and manifest.json asynchronously altogether while avoiding inline scripts or a separate bootstrap script at the same time.

  1. Run the app with the xx-nosync bootstrap option. For example, in the URL:

    https://&lthost>/my/awesome/app/?sap-ui-xx-nosync=warn

    UI5 will then log "loading … with sync XHR" in the browser console for each of the files fetched synchronously (Ignore other [nosync] messages). For example:

    • If the app uses a v2.ODataModel, it might complain that the module sap/ui/thirdparty/datajs was loaded synchronously. In that case, add the following to the bootstrap config:
      <script id="sap-ui-bootstrap" ...
        data-sap-ui-async="true"
        data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
        data-sap-ui-modules="sap/ui/thirdparty/datajs"
      ></script>
    • If a ResourceModel is created manually in JS, make sure to enable the async flag there:
      const i18nModel = new ResourceModel({ // required by "sap/ui/model/resource/ResourceModel"
        bundleName: "demo.i18n.i18n",
        supportedLocales: [""],
        fallbackLocale: "",
        async: true, // <--
      });
      i18nModel.getResourceBundle().then(resourceBundle => {
        this.getOwnerComponent().setModel(i18nModel, "i18n");
        resourceBundle.getText(/*...*/); // See sap/base/i18n/ResourceBundle
      });

    Check the API reference of the reported APIs. Most of the times, they're either deprecated or they come with an async flag set to false by default.

There are still some APIs left which have no asynchronous replacements yet such as:

  • The CLDR file being fetched with sync XHR when instantiating sap/ui/core/LocaleData (Used in e.g. Calendar or DatePicker. See Issue #2345).
  • When resolving i18n Handlebar-like "{{...}}"-syntax in manifest.json

With the latest stable version of UI5, however, most of the synchronous requests can be eliminated.
Here is a sample that has no sync XHR: https://embed.plnkr.co/7txzTsNwOBDbyi87


To answer the question: sap.ui.define and sap.ui.require do load dependencies asynchronously if the data-sap-ui-async config is set to true (Replaces data-sap-ui-preload="async"). Also make sure to add dependent libs to the manifest.json in order to prevent a major performance bottleneck.

Wrapping a synchronous content request with async-await/Promise won't unfortunately help. Better look for asynchronous alternatives. For example, the ComponentContainer has an async flag in the constructor settings which, if enabled, fetches the Component.js and manifest.json files asynchronously:

new ComponentContainer({
  height: "100%",
  name: "webapp",
  async: true, // or
  manifest: true, // sets the `async` option automatically to true
})



回答2:


The Synchronous XMLHttpRequest warning in the console might be from leftovers from the actual core. I know the launchpad has some issues in this regard. If you time it or have a closer look at your network tab / sources tab you'll find the message is displayed before your own code is loaded.

Somewhere in a file like sap.jquery.js or something along those lines you'll find XMLHtppRequests with the sync flag set. I've had conversations with the UI5 team about it and removing it is on the radar but no timelines are provided.

To answer your question more directly, the require parts are meant to be asynchronous. It's an idea taken from require js which is at least 10 years old by now.

// edit

async/await is not going to do anything since none of that is promise based. Doing sap.m.Shell is just assuming that the window object has the sap.m library attached to it before your controller loads, which you can make sure to preload through your manifest for instance.



来源:https://stackoverflow.com/questions/64404429/how-to-avoid-synchronous-xmlhttprequest-on-the-main-thread-warning-in-ui5

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!