Angular ssr, проблема с перерисовкой страницы - PullRequest
0 голосов
/ 13 апреля 2020

Я новичок в Angular ssr, вы можете увидеть код ниже

Issue

Если я ввожу клиентский маршрут напрямую, сначала он показывает

Предоставляется сервером

, но быстро после этого он перерисовывает страницу и показывает:

Предоставляется браузером

Думаю, я знаю, почему это происходит, но кто-нибудь может дать хорошее объяснение? Кроме того, могу ли я как-то избежать этого поведения и заставить браузер отображать html, который приходит с сервера? я должен беспокоиться об этом?

client.component.ts

@Component({
  selector: "client",
  template: "<p>Rendered by {{ renderer }}</p>",
  styleUrls: ["./dumco.component.css"]
})
export class ClientComponent implements OnInit {

  renderer: string;
  bla: any = [];

  constructor(private http: HttpClient, @Inject(PLATFORM_ID) platformId: any) {
    this.renderer = isPlatformBrowser(platformId) ? "Browser" : "Server";
  }
}

app-routing.module.ts

import { NgModule } from "@angular/core";
import { RouterModule, PreloadAllModules } from "@angular/router";
import { AppComponent } from "./app.component";
import { CompfComponent } from "./compf/compf.component"
import { HomeComponent } from "./home/home.component"

export const appRoutes = [
  {
    path: "",
    component: HomeComponent
  },
  {
    path: "comp",
    component: CompfComponent
  },
  {
    path: "client",
    loadChildren: () => import("./client/client.module").then(m => m.ClientModule),
    data: { title: "Static Data - Clients" }
  },
];

// preloadingStrategy: PreloadAllModules,
@NgModule({
  imports: [RouterModule.forRoot(appRoutes, { onSameUrlNavigation: "reload", initialNavigation: 'enabled' })],
  exports: [RouterModule]
})
export class AppRoutingModule { }

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from "@angular/common/http";

import { AppRoutingModule } from "./app-routing.module"

import { AppComponent } from './app.component';
import { CompfComponent } from './compf/compf.component';
import { HomeComponent } from './home/home.component';

import { TransferHttpCacheModule } from "@nguniversal/common"

@NgModule({
  declarations: [
    AppComponent,
    CompfComponent,
    HomeComponent
  ],
  imports: [
    HttpClientModule,
    TransferHttpCacheModule,
    BrowserModule.withServerTransition({ appId: 'serverApp' }),
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

app.server.module.ts

import { NgModule } from '@angular/core';
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server';

import { AppModule } from './app.module';
import { AppComponent } from './app.component';

@NgModule({
  imports: [
    AppModule,
    ServerModule,
    ServerTransferStateModule
  ],
  bootstrap: [AppComponent],
})
export class AppServerModule {}

1 Ответ

1 голос
/ 13 апреля 2020

Это нормальное поведение для angular универсального. Вот обычный поток:

  1. Вы делаете запрос к серверу
  2. Angular universal создает и рендерит компоненты (включая вызовы API) на стороне сервера для генерации HTML содержание. Содержимое отправляется обратно в браузер клиента. (В вашем примере HTML будет содержать «отрендеренный сервером»)
  3. Браузер рендерит HTML.
  4. После рендеринга страницы и загрузки документа DOM, клиент Приложение angular на стороне загружено.
  5. Приложение angular на стороне клиента создает и отображает компоненты (и выполняет вызовы API). В вашем случае он будет отображаться как «показанный браузером».

На самом деле вам не нужно беспокоиться об этом. В реальной ситуации ваши компоненты будут выполнять вызовы API. Чтобы клиентская сторона не выполняла те же вызовы, которые уже были сделаны на стороне сервера, вы можете использовать angular TransferState для сериализации данных API на стороне сервера, сгенерированной HTML, чтобы клиентская сторона могла использовать эти данные напрямую вместо повторных вызовов API.

Таким образом, HTML, сгенерированный клиентом, должен совпадать с тем, который пришел с сервера. (Если, конечно, вы специально не отображаете разные серверы данных и стороны клиента, как в вашем примере)

...