Angular 7 SSR,应用程序组件 ngOnInit() 多次调用

问题描述 投票:0回答:4

我有一个 Angular 7 应用程序,包含大约 30 个模块。我正在

app.component.ts
中获取用户详细信息,以便在整个应用程序中使用它,但我突然注意到用户详细信息 API 在 1 次加载时运行多次。

将日志放入

ngOnInit()
中的
app.component.ts
中后,我发现日志会打印多次,但仅发生在浏览器上的服务器端渲染上,它仅渲染一次。

知道为什么

ngOnInit()
多次打电话吗?

javascript angular server-side-rendering angular-universal
4个回答
3
投票

Angular SSR 的概念是,在第一次加载页面/URL 时,它通过服务器呈现,然后在客户端传输数据。因此从技术上讲,它会调用所有组件,服务在该页面/URL 上存在两次。

您可以使用条件 isPlatformBrowser 和 isPlatformServer 方法,这样您就可以在服务器端仅渲染所需的部分。我们只在 SSR 上渲染与 SEO 优化相关的特定内容。


0
投票

ngOnInit() 在所有指令实例化后仅挂钩一次。如果您在 ngOnInit() 内有订阅并且未取消订阅,那么如果订阅的数据发生更改,它将再次运行。在您的情况下,当通过服务器端的 SSR 加载 API 调用时,服务器并不总是等待响应的到来,这可能是多个日志的原因。建议使用 isPlatformBrowser 将其委托给客户端。这是我根据对一般 SSR 流程的调查得出的结果。


0
投票

我不确定这个问题是否已经解决,但这里有一个建议:

在组件本身中添加

subscribe
部分,并将其从进行 HTTP 调用的函数中删除:

ngOnInit() {
    this.loadData();
}

loadData(){
    this.my_service.getData().subscribe(data => this.userDetails = data);
}

在您的服务中,您可以进行普通的 HTTP 调用:

getData() {
    return this.http.get('../your/url')
           .map((res:Response) => res.json());
}

我希望这有帮助。


0
投票

在除 afterRender 和 afterNextRender 之外的 SSR 中,构造函数和初始生命周期挂钩将在服务器和浏览器中执行。

我们可以对httpClient调用实现缓存,以避免多次api调用。

bootstrapApplication(AppComponent, { providers: [ provideClientHydration(withHttpTransferCacheOptions({ includePostRequests: true })) ] });

或者我们可以使用 PLATFORM_ID 与 isPlatformBrowser 和 isPlatformServer 来识别它是在服务器还是客户端中渲染

import { PLATFORM_ID } from '@angular/core';
import {  isPlatformBrowser, isPlatformServer } from '@angular/common';
ngOnInit(): void {
    if(isPlatformBrowser(this.platformId)){
      // runs on client / browser
      console.log("from browser.");
    }
    if(isPlatformServer(this.platformId)){
      // runs on server / node
      console.log("from server");
    }
  }
© www.soinside.com 2019 - 2024. All rights reserved.