我有一个Angular 9(v9.0.6)应用程序,可以在其中与Universal(SSR)一起正常工作,当我注意到该应用程序挂载了100%CPU消耗时,在移至PROD之前我正在执行最后一组测试。我分析了错误,结果发现当Angular应用直接加载路由时,这是一个问题,该路由是执行HTTP调用的延迟加载模块。
如果我通过Home(或没有HTTP的其他路由,但即使有home,也加载了另一个延迟加载的模块,具有进行HTTP调用的相同组件)加载角度,则一切正常。我可以导航到所有路线而没有任何问题,APP的魅力十足。但是,如果我直接说在新选项卡中www.mywebsite / lazy-loaded-module,我相信引导过程中有些东西会阻止所有注册或至少HTTPClientModule正确注册,并且然后我失败了。
首先,我在HTTPClientModule
中只注册了一次AppModule
。我得到的错误是:
(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
。
答案 0 :(得分:1)
是的,如果您知道如何让angular知道请求是由SSR服务器发出的,则有更好的方法来实现动画。
就这样。
您可以看到server.ts
有一个注入令牌。
providers: [
{ provide: APP_BASE_HREF, useValue: req.baseUrl },
现在您需要做的是进入组件并像下面那样注入此令牌。
constructor(
@Optional() @Inject(APP_BASE_HREF) private basehref: string,
如果basehref
不是SSR,则为空;如果通过SSR请求,则为某个字符串值。
现在提供一种仅在basehref
为空时执行动画的方法。