Angular ssr,页面呈现问题
Angular ssr, page rerender issue
我是Angular ssr新手,可以看下面的代码
问题
如果我直接进入客户端路由,首先显示
Rendered by server
但很快就会重新呈现页面并显示:
Rendered by browser
我想我知道为什么会这样,但是可以肯定有人可以提供一个很好的解释吗?另外,我能以某种方式避免这种行为并强制浏览器呈现来自服务器的 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 {}
这是 angular 通用的正常行为。这是正常流程:
- 您向服务器发出请求
- Angular 通用创建和呈现组件(包括 API 调用)服务器端以生成 HTML 内容。内容被发送回客户端浏览器。 (在您的示例中,HTML 将包含 "rendered by server")
- 浏览器呈现 HTML。
- 呈现页面并加载 dom 文档后,将启动客户端 angular 应用程序。
- 客户端 angular 应用创建和呈现组件(并进行 API 调用)。它将在您的情况下呈现 "rendered by browser"。
你真的不必担心这个。在实际情况下,您会让您的组件进行 API 调用。为了防止客户端进行与服务器端相同的调用,您可以使用 angular TransferState
序列化 HTML 生成的服务器端中的 API 数据,这样客户端就可以立即使用该数据,而不是再次进行 API 调用。
这样,客户端生成的 HTML 应该与服务器端生成的相同。 (当然除非你特别显示不同的数据服务器和客户端,就像你的例子一样)
我是Angular ssr新手,可以看下面的代码
问题
如果我直接进入客户端路由,首先显示
Rendered by server
但很快就会重新呈现页面并显示:
Rendered by browser
我想我知道为什么会这样,但是可以肯定有人可以提供一个很好的解释吗?另外,我能以某种方式避免这种行为并强制浏览器呈现来自服务器的 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 {}
这是 angular 通用的正常行为。这是正常流程:
- 您向服务器发出请求
- Angular 通用创建和呈现组件(包括 API 调用)服务器端以生成 HTML 内容。内容被发送回客户端浏览器。 (在您的示例中,HTML 将包含 "rendered by server")
- 浏览器呈现 HTML。
- 呈现页面并加载 dom 文档后,将启动客户端 angular 应用程序。
- 客户端 angular 应用创建和呈现组件(并进行 API 调用)。它将在您的情况下呈现 "rendered by browser"。
你真的不必担心这个。在实际情况下,您会让您的组件进行 API 调用。为了防止客户端进行与服务器端相同的调用,您可以使用 angular TransferState
序列化 HTML 生成的服务器端中的 API 数据,这样客户端就可以立即使用该数据,而不是再次进行 API 调用。
这样,客户端生成的 HTML 应该与服务器端生成的相同。 (当然除非你特别显示不同的数据服务器和客户端,就像你的例子一样)