【发布时间】:2020-07-26 00:34:12
【问题描述】:
我有一个 Angular 9 (v9.0.6) 应用程序可以与 Universal (SSR) 一起正常工作,当我注意到应用程序以 100% 的 CPU 消耗挂起时,我正在执行最后一组测试,然后再转移到 PROD。我分析了这个错误,当 Angular 应用程序直接加载一个执行 HTTP 调用的延迟加载模块的路由时,结果证明是一个问题。
如果我通过 Home(或另一个没有 HTTP 的路由 - 但即使是 home,另一个延迟加载的模块具有相同的组件来进行 HTTP 调用)加载角度,一切都可以正常工作。我可以毫无问题地导航到所有路线,并且 APP 就像一个魅力。但是,如果我去,让 www.mywebsite/lazy-loaded-module 直接在一个新选项卡中说,我相信引导过程中有一些东西阻止所有 tregistrations 或至少 HTTPClientModule 正确注册并且然后我就失败了。
首先,我在AppModule 中只注册了一次HTTPClientModule。我得到的错误是:
(node:17624) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
CPU 达到 100%,应用程序挂起。同样,如果我转到 www.my-website.com 则不会发生这种情况,然后我通过应用程序导航到 /my-lazy-loaded-module
然后我尝试了其他方法:在我的延迟加载模块中包括(我知道我不应该)HTTPClientModule,它在 CPU 问题中的工作方式消失了,但是我得到了一个不同的错误:
ReferenceError: XMLHttpRequest is not defined
at BrowserXhr.build
这会对我使用 SSR 检索并呈现的内容产生影响,因为没有。作为一种可以做到的解决方法,但我想知道应该如何解决这个问题。我执行的node 版本是:v10.16.2
更新
为了更清楚地了解我正在进行的 HTTP 调用,我只是一个标准调用:
public getNext = (page: number, pageSize: number): Promise<IEventsPaged> => {
return this.http.get<IEventsPaged>(`${environment.apiBaseUrl}/events?page=${page}&pageSize=${pageSize})
.toPromise()
.then(r => r)
.catch((error: Response | any) => {
return Promise.reject(error);
});
}
更新 2
我已更新到 Angular 9.1.1,它修复了缓冲区警告。应用程序仍然挂起,并且只发生在一个模块上。其他模块也在进行 http 调用(相同的标准 get,但使用不同的服务)而没有问题。
** 更新 3 **
我找到了问题的根本原因。它最终与 HTTP 无关。发生的事情是,在我所指的页面中,我有一个非常简单的角度动画。这是一个通过标准角度动画应用无限动画的三角形,它会变大或变小。为了实现无限效果,我连接到animation.done 事件以将状态更改为大或小。好吧,如果你在放置动画的那条路线上硬刷新页面,你最终会陷入这样的无限循环:
{ element:
HTMLDivElement {
parentNode:
HTMLUnknownElement {
parentNode: [HTMLDivElement],
_previousSibling: [HTMLDivElement],
_nextSibling: [HTMLImageElement],
_index: undefined,
_childNodes: null,
_firstChild: [Circular],
nodeType: 1,
ownerDocument: [Object],
localName: 'app-bottom-angle',
namespaceURI: 'http://www.w3.org/1999/xhtml',
prefix: null,
_tagName: undefined,
_attrsByQName: [Object],
_attrsByLName: [Object],
_attrKeys: [Array],
__ngContext__: [LComponentView_CalendarIntroductionComponent],
_classList: [DOMTokenList],
_nid: 79 },
_previousSibling: [Circular],
_nextSibling: [Circular],
_index: undefined,
_childNodes: null,
_firstChild: null,
nodeType: 1,
ownerDocument:
{ parentNode: null,
_previousSibling: [Circular],
_nextSibling: [Circular],
_index: undefined,
_childNodes: null,
_firstChild: [Object],
nodeType: 9,
isHTML: true,
_address: 'http://localhost:54818/en/calendar',
readyState: 'loading',
implementation: [Object],
ownerDocument: null,
_contentType: 'text/html',
doctype: [Object],
documentElement: [HTMLHtmlElement],
_templateDocCache: null,
_nodeIterators: null,
_nid: 1,
_nextnid: 152,
_nodes: [Array],
byId: [Object],
modclock: 23,
_scripting_enabled: true,
defaultView: [Object],
_lastModTime: 1 },
localName: 'div',
namespaceURI: 'http://www.w3.org/1999/xhtml',
prefix: null,
_tagName: undefined,
_attrsByQName:
[Object: null prototype] { '_ngcontent-sc33': [Object], class: [Object], style: [Object] },
_attrsByLName:
[Object: null prototype] {
'|_ngcontent-sc33': [Object],
'|class': [Object],
'|style': [Object] },
_attrKeys: [ '|_ngcontent-sc33', '|class', '|style' ],
_classList:
DOMTokenList {
'0': 'position-absolute',
'1': 'z-index-plus-1',
'2': 'bottom-0',
'3': 'right-0',
'4': 'left-0',
'5': 'mb-4',
'6': 'ng-tns-c33-1',
'7': 'ng-trigger',
'8': 'ng-trigger-scale',
'9': undefined,
'10': undefined,
_getString: [Function],
_setString: [Function],
_length: 9 },
__ngContext__:
LComponentView_BottomAngleComponent [
[HTMLUnknownElement],
[TView],
211,
[LComponentView_CalendarIntroductionComponent],
null,
null,
[TNode$1],
[LCleanup],
[BottomAngleComponent],
[Object],
[AnimationRendererFactory],
[AnimationRenderer],
null,
null,
null,
[LComponentView_CalendarIntroductionComponent],
[Circular],
null,
0,
[Circular],
'big' ],
_nid: 80,
_style:
{ _element: [Circular],
_parsedStyles: [Object],
_lastParsedText: 'transform: scale(1); transform-style: preserve-3d;',
_names: [Array] } },
triggerName: 'scale',
fromState: 'small',
toState: 'big',
phaseName: 'done',
totalTime: 1200,
disabled: false,
_data: 1006 }
{ element:
HTMLDivElement {
parentNode:
HTMLUnknownElement {
parentNode: [HTMLDivElement],
_previousSibling: [HTMLDivElement],
_nextSibling: [HTMLImageElement],
_index: undefined,
_childNodes: null,
_firstChild: [Circular],
nodeType: 1,
ownerDocument: [Object],
localName: 'app-bottom-angle',
namespaceURI: 'http://www.w3.org/1999/xhtml',
prefix: null,
_tagName: undefined,
_attrsByQName: [Object],
_attrsByLName: [Object],
_attrKeys: [Array],
__ngContext__: [LComponentView_CalendarIntroductionComponent],
_classList: [DOMTokenList],
_nid: 79 },
_previousSibling: [Circular],
_nextSibling: [Circular],
_index: undefined,
_childNodes: null,
_firstChild: null,
nodeType: 1,
ownerDocument:
{ parentNode: null,
_previousSibling: [Circular],
_nextSibling: [Circular],
_index: undefined,
_childNodes: null,
_firstChild: [Object],
nodeType: 9,
isHTML: true,
_address: 'http://localhost:54818/en/calendar',
readyState: 'loading',
implementation: [Object],
ownerDocument: null,
_contentType: 'text/html',
doctype: [Object],
documentElement: [HTMLHtmlElement],
_templateDocCache: null,
_nodeIterators: null,
_nid: 1,
_nextnid: 152,
_nodes: [Array],
byId: [Object],
modclock: 23,
_scripting_enabled: true,
defaultView: [Object],
_lastModTime: 1 },
localName: 'div',
namespaceURI: 'http://www.w3.org/1999/xhtml',
prefix: null,
_tagName: undefined,
_attrsByQName:
[Object: null prototype] { '_ngcontent-sc33': [Object], class: [Object], style: [Object] },
_attrsByLName:
[Object: null prototype] {
'|_ngcontent-sc33': [Object],
'|class': [Object],
'|style': [Object] },
_attrKeys: [ '|_ngcontent-sc33', '|class', '|style' ],
_classList:
DOMTokenList {
'0': 'position-absolute',
'1': 'z-index-plus-1',
'2': 'bottom-0',
'3': 'right-0',
'4': 'left-0',
'5': 'mb-4',
'6': 'ng-tns-c33-1',
'7': 'ng-trigger',
'8': 'ng-trigger-scale',
'9': undefined,
'10': undefined,
_getString: [Function],
_setString: [Function],
_length: 9 },
__ngContext__:
LComponentView_BottomAngleComponent [
[HTMLUnknownElement],
[TView],
211,
[LComponentView_CalendarIntroductionComponent],
null,
null,
[TNode$1],
[LCleanup],
[BottomAngleComponent],
[Object],
[AnimationRendererFactory],
[AnimationRenderer],
null,
null,
null,
[LComponentView_CalendarIntroductionComponent],
[Circular],
null,
0,
[Circular],
'small' ],
_nid: 80,
_style:
{ _element: [Circular],
_parsedStyles: [Object],
_lastParsedText: 'transform: scale(1.2); transform-style: preserve-3d;',
_names: [Array] } },
triggerName: 'scale',
fromState: 'big',
toState: 'small',
phaseName: 'done',
totalTime: 1200,
disabled: false,
_data: 1007 }
然后您的应用程序挂起。我不知道是否有更好的方法来使用 Angular 动画实现无限动画,以及是否应该由开发人员“知道”SSR 会受到它们的攻击。我想如果你认为它们处理 HTML 元素,你可能会争辩说它们都应该在其中使用 isPlatformBrowser。
【问题讨论】:
-
你有
APP_INITIALIZER令牌的提供者吗? -
不,我没有。是不是我必须对其进行配置,以便在导航到延迟加载的模块之前以某种方式使 http 可用?
-
不,我只是想知道 APP_INITIALIZER 是否引起了问题
-
我刚刚注意到有另一个模块具有几乎相同的结构并且工作正常。我不确定发生了什么,但如果我不执行 HTTP 调用,应用程序可以正常工作
-
你能尝试向惰性模块调用的同一个 url 发出 API 请求服务器端(例如使用 curl)吗?
标签: node.js angular angular-universal angular-animations