如何避免 UI5 中的 "Synchronous XMLHttpRequest on the main thread" 警告?
How to avoid "Synchronous XMLHttpRequest on the main thread" warning in UI5?
我正在用 index.js
中的以下引导启动我的 UI5:
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");
});
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.
我的理解是否正确,在这种情况下,模块将始终以同步方式加载,并且没有真正的方法来避免 «主线程上的同步 XMLHttpRequest» 警告?
也许我可以将 new sap.m.Shell(sId?, mSettings?)
换成 async
/await
吗?
更新 #1:
我用 ?sap-ui-xx-nosync=warn
检查了加载并得到了以下结果:
出于某种原因 i18n/i18n_en.properties
被同步加载。我访问 i18n
的唯一地方是:
const oBundle = myI18nModel.getResourceBundle();
但是按照文档,我无法理解为什么myI18nModel.getResourceBundle()
会导致同步加载。
更新#2:
在深入研究 no sync XHR 示例后,我找到了 sync XHR
警告的原因。那是 "description": "{{appDescription}}"
和 "title": "{{appTitle}}"
in manifest.json
明确指出:
"title": "Here the i18n bundles can't be loaded with 'async: true' yet!",
"description": "Same here. Hence, no 'i18n' in this 'sap.app' section!"
用静态值替换后警告消失。
控制台中的同步 XMLHttpRequest
警告可能来自实际核心的剩余部分。我知道启动板在这方面存在一些问题。如果您计时或仔细查看您的网络选项卡/源选项卡,您会发现在加载您自己的代码之前会显示该消息。
在像 sap.jquery.js
这样的文件中的某处或类似的行中,您会发现 XMLHtppRequests
设置了 sync
标志。我已经与 UI5 团队就此进行了对话,并考虑将其移除,但未提供时间表。
为了更直接地回答您的问题,require
部分是异步的。这个想法取自 require js,现在至少已有 10 年历史了。
// 编辑
async
/await
不会做任何事情,因为 none 是基于承诺的。执行 sap.m.Shell
只是假设 window 对象在控制器加载之前附加了 sap.m
库,例如,您可以确保通过清单预加载。
UI5 的早期开发很大程度上基于 synchronous XHRs。遗留应用程序或一些过时的文档主题可能仍然引用 APIs,它们默认禁用 异步选项 或 没有异步选项 完全如:sap.ui.controller
、sap.ui.component
、sap.ui.*fragment
、sap.ui.*view
、jQuery.sap.require
、sap.ui.requireSync
、jQuery.sap.sjax
和构造函数问题中提到的 ComponentContainer
的功能。
为了减少同步 XHR 调用的次数:
遵循记录的指南:
特别是当 bootstrapping 时,使用 data-sap-ui-async="true"
选项,并且,如果应用程序有 Component.js
,use the declarative sap/ui/core/ComponentSupport
module in data-sap-ui-oninit
而不是手动实例化 sap.ui.core.ComponentContainer
.例如:
<头>
<!-- ... -->
<脚本 ID="sap-ui-bootstrap" ...
data-sap-ui-async="true"
<strong>data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"</strong>
></脚本>
</头>
<正文 ID="content" class="sapUiBody">
<div data-sap-ui-component
data-id="rootComponentContainer"
data-name="demo"
data-settings='{ "id": "rootComponent" }'
...
></div>
</body>
这会自动创建一个 ComponentContainer
,将其推送到 DOM,并异步加载 Component.js
和 manifest.json
完全同时避免内联脚本或单独的 bootstrap 脚本。
运行 带有 xx-nosync
bootstrap option 的应用程序。例如,在 URL:
https://<host>/my/awesome/app/?<strong>sap-ui-xx-nosync=警告</strong>
UI5 将在浏览器控制台中记录 “正在使用同步 XHR 加载” 同步获取的每个文件(忽略其他 [nosync] 消息)。例如:
- 如果应用程序使用
v2.ODataModel
,它可能会抱怨模块 sap/ui/thirdparty/datajs
是同步加载的。在这种情况下,将以下内容添加到 bootstrap 配置中:
<脚本 ID="sap-ui-bootstrap" ...
data-sap-ui-async="true"
data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
<strong>data-sap-ui-modules="sap/ui/thirdparty/datajs"</strong>
></script>
- 如果在 JS 中手动创建
ResourceModel
,请确保在那里启用 async
标志:
const i18nModel = new ResourceModel({ // "sap/ui/model/resource/ResourceModel" 要求
bundleName: "demo.i18n.i18n",
支持的语言环境:[“”],
fallbackLocale:“”,
<strong>异步:真</strong>, // <--
});
i18nModel.getResourceBundle().then(resourceBundle => {
this.getOwnerComponent().setModel(i18nModel, "i18n");
resourceBundle.getText(/*...*/); // 见 sap/base/i18n/ResourceBundle
});
检查报告的 API 的 API 引用。大多数时候,它们要么被弃用,要么带有默认设置为 false
的 async
标志。
还有一些 API 还没有异步替换 例如:
- CLDR file being fetched with sync XHR when instantiating
sap/ui/core/LocaleData
(Used in e.g. Calendar or DatePicker. See Issue #2345).
- 解析 i18n 时 Handlebar-like
"{{...}}"
-manifest.json
中的语法
使用最新的稳定版UI5,可以消除大部分同步请求。
这是一个没有同步 XHR 的 样本:https://embed.plnkr.co/7txzTsNwOBDbyi87
回答问题:sap.ui.define
和 sap.ui.require
异步加载依赖项 如果 data-sap-ui-async
配置设置为 true
. Also make sure to 以防止出现主要的性能瓶颈。
用 async-await
/Promise
包装同步内容请求不会有帮助。最好寻找异步替代方案。例如,ComponentContainer
在构造函数设置中有一个 async
标志,如果启用,它会异步获取 Component.js
和 manifest.json
文件:
新组件容器({
高度:“100%”,
姓名:"webapp",
<strong>异步:真,//或
manifest: true, // 将 `async` 选项自动设置为 true</strong>
})
我正在用 index.js
中的以下引导启动我的 UI5:
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");
});
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.
我的理解是否正确,在这种情况下,模块将始终以同步方式加载,并且没有真正的方法来避免 «主线程上的同步 XMLHttpRequest» 警告?
也许我可以将 new sap.m.Shell(sId?, mSettings?)
换成 async
/await
吗?
更新 #1:
我用 ?sap-ui-xx-nosync=warn
检查了加载并得到了以下结果:
出于某种原因 i18n/i18n_en.properties
被同步加载。我访问 i18n
的唯一地方是:
const oBundle = myI18nModel.getResourceBundle();
但是按照文档,我无法理解为什么myI18nModel.getResourceBundle()
会导致同步加载。
更新#2:
在深入研究 no sync XHR 示例后,我找到了 sync XHR
警告的原因。那是 "description": "{{appDescription}}"
和 "title": "{{appTitle}}"
in manifest.json
明确指出:
"title": "Here the i18n bundles can't be loaded with 'async: true' yet!",
"description": "Same here. Hence, no 'i18n' in this 'sap.app' section!"
用静态值替换后警告消失。
控制台中的同步 XMLHttpRequest
警告可能来自实际核心的剩余部分。我知道启动板在这方面存在一些问题。如果您计时或仔细查看您的网络选项卡/源选项卡,您会发现在加载您自己的代码之前会显示该消息。
在像 sap.jquery.js
这样的文件中的某处或类似的行中,您会发现 XMLHtppRequests
设置了 sync
标志。我已经与 UI5 团队就此进行了对话,并考虑将其移除,但未提供时间表。
为了更直接地回答您的问题,require
部分是异步的。这个想法取自 require js,现在至少已有 10 年历史了。
// 编辑
async
/await
不会做任何事情,因为 none 是基于承诺的。执行 sap.m.Shell
只是假设 window 对象在控制器加载之前附加了 sap.m
库,例如,您可以确保通过清单预加载。
UI5 的早期开发很大程度上基于 synchronous XHRs。遗留应用程序或一些过时的文档主题可能仍然引用 APIs,它们默认禁用 异步选项 或 没有异步选项 完全如:sap.ui.controller
、sap.ui.component
、sap.ui.*fragment
、sap.ui.*view
、jQuery.sap.require
、sap.ui.requireSync
、jQuery.sap.sjax
和构造函数问题中提到的 ComponentContainer
的功能。
为了减少同步 XHR 调用的次数:
遵循记录的指南:
特别是当 bootstrapping 时,使用
data-sap-ui-async="true"
选项,并且,如果应用程序有Component.js
,use the declarativesap/ui/core/ComponentSupport
module indata-sap-ui-oninit
而不是手动实例化sap.ui.core.ComponentContainer
.例如:<头> <!-- ... --> <脚本 ID="sap-ui-bootstrap" ... data-sap-ui-async="true" <strong>data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"</strong> ></脚本> </头> <正文 ID="content" class="sapUiBody"> <div data-sap-ui-component data-id="rootComponentContainer" data-name="demo" data-settings='{ "id": "rootComponent" }' ... ></div> </body>
这会自动创建一个
ComponentContainer
,将其推送到 DOM,并异步加载Component.js
和manifest.json
完全同时避免内联脚本或单独的 bootstrap 脚本。
运行 带有
xx-nosync
bootstrap option 的应用程序。例如,在 URL:https://<host>/my/awesome/app/?<strong>sap-ui-xx-nosync=警告</strong>
UI5 将在浏览器控制台中记录 “正在使用同步 XHR 加载” 同步获取的每个文件(忽略其他 [nosync] 消息)。例如:
- 如果应用程序使用
v2.ODataModel
,它可能会抱怨模块sap/ui/thirdparty/datajs
是同步加载的。在这种情况下,将以下内容添加到 bootstrap 配置中:<脚本 ID="sap-ui-bootstrap" ... data-sap-ui-async="true" data-sap-ui-oninit="module:sap/ui/core/ComponentSupport" <strong>data-sap-ui-modules="sap/ui/thirdparty/datajs"</strong> ></script>
- 如果在 JS 中手动创建
ResourceModel
,请确保在那里启用async
标志:const i18nModel = new ResourceModel({ // "sap/ui/model/resource/ResourceModel" 要求 bundleName: "demo.i18n.i18n", 支持的语言环境:[“”], fallbackLocale:“”, <strong>异步:真</strong>, // <-- }); i18nModel.getResourceBundle().then(resourceBundle => { this.getOwnerComponent().setModel(i18nModel, "i18n"); resourceBundle.getText(/*...*/); // 见 sap/base/i18n/ResourceBundle });
检查报告的 API 的 API 引用。大多数时候,它们要么被弃用,要么带有默认设置为
false
的async
标志。- 如果应用程序使用
还有一些 API 还没有异步替换 例如:
- CLDR file being fetched with sync XHR when instantiating
sap/ui/core/LocaleData
(Used in e.g. Calendar or DatePicker. See Issue #2345). - 解析 i18n 时 Handlebar-like
"{{...}}"
-manifest.json
中的语法
使用最新的稳定版UI5,可以消除大部分同步请求。
这是一个没有同步 XHR 的 样本:https://embed.plnkr.co/7txzTsNwOBDbyi87
回答问题:sap.ui.define
和 sap.ui.require
异步加载依赖项 如果 data-sap-ui-async
配置设置为 true
用 async-await
/Promise
包装同步内容请求不会有帮助。最好寻找异步替代方案。例如,ComponentContainer
在构造函数设置中有一个 async
标志,如果启用,它会异步获取 Component.js
和 manifest.json
文件:
新组件容器({
高度:“100%”,
姓名:"webapp",
<strong>异步:真,//或
manifest: true, // 将 `async` 选项自动设置为 true</strong>
})