在《Angular Universal(SSR)的重复加载问题》一文中曾经介绍过Angular v14.x
版本中出现的重复加载(flickering)问题,并给出了解决方案。然而,升级到Angular v15.x
后,重复加载问题再次出现了。
诡异的是,实际上,state
在服务端是正常调用并在页面缓存了的。如下:
typescriptCopy code- 1
- 2
- 3
- 4
console.log(1, storedResponse);
console.log(2, this.state.get(key, null));
console.log(3, this.state.toJson());
console.log(4, JSON.stringify(this.state));
console.log(1, storedResponse);
console.log(2, this.state.get(key, null));
console.log(3, this.state.toJson());
console.log(4, JSON.stringify(this.state));
以上代码中,第一行输出是能够正常看到完整的值的,然而,第2-4行的输出却是空白的。因此,怀疑是在存值和取值的过程中二者不同步所导致的,或者,取值逻辑发生了变化。
但,知道了问题,却找不到解决方案。┓( ´∀` )┏
此时摆在面前的选择只有2个:
- 回退到
Angular v14.x
; - or,找到治本的适配
Angular v15.x
的解决方案。
继续在网上溜达,在GitHub
的issue中找到这么一条回复:
The current version of Angular uses destructive hydration which causes flickering, but the workarounds mentioned in the comments works well to address this issue. You can say its a limitation of the framework, but this is how it works in the current version of Angular.
可以确定是Angular v15.x
的一些“破坏性更新”导致的此问题,因此回头去翻了下release notes
,找到这么两篇:TransferState和Standalone migration,其中,ServerTransferStateModule
显示为DEPRECATED
状态,而renderApplication
则显示为开发者预览状态,似乎都不太靠谱。
最后,只能死马当活马医,迁移到Standalone
模式。
按照上述链接的文档执行以下命令3次,分别在给出的选项中选择不同的操作:
bashCopy code
- 1
ng generate @angular/core:standalone
ng generate @angular/core:standalone
然后,启动服务,根据给出的报错提示逐一修改,完成之后再次启动服务,显示熟悉的页面且控制台无报错时,即表示成功。
然而,执行npm run dev:ssr
切换到SSR
模式时,却报错:
error NG6009: The `AppComponent` class is a standalone component, which can not be used in the `@NgModule.bootstrap` array. Use the `bootstrapApplication` function for bootstrap instead.
报错信息已经很清楚了,将AppComponent
改回原来的方式即可,然后重新创建app.module.ts
文件,内容如下:
typescriptCopy code- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule.withServerTransition({ appId: 'ifuyun' }),
TransferHttpCacheModule,
AppRoutingModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
BrowserAnimationsModule,
CommonModule,
HeaderComponent,
FooterComponent,
SiderComponent,
ToolboxComponent,
BackTopComponent
],
providers: [
httpInterceptorProviders,
{ provide: APP_BASE_HREF, useValue: env.host },
provideHttpClient(withInterceptorsFromDi()),
provideAnimations()
],
bootstrap: [AppComponent]
})
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule.withServerTransition({ appId: 'ifuyun' }),
TransferHttpCacheModule,
AppRoutingModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
BrowserAnimationsModule,
CommonModule,
HeaderComponent,
FooterComponent,
SiderComponent,
ToolboxComponent,
BackTopComponent
],
providers: [
httpInterceptorProviders,
{ provide: APP_BASE_HREF, useValue: env.host },
provideHttpClient(withInterceptorsFromDi()),
provideAnimations()
],
bootstrap: [AppComponent]
})
再次启动服务,完美![]~( ̄▽ ̄)~*
此时,再去测试SSR
环境下的重复加载问题,发现也“被”解决了……╰(*°▽°*)╯
然而,执行npm outdated
时却突然发现,Angular
已经悄悄升级到v15.2.1
了,怀疑是不是之前的v15.2.0
版本的问题,而不是Standalone Component
所致?
回退代码到迁移Standalone Component
之前,并且更新Angular
至v15.2.1
,再次测试,果然!
再去看GitHub
上的版本提交记录,似乎得到了印证。
看来闹了一出乌龙……But,不管怎么说,问题解决了便是最好的……[]~( ̄▽ ̄)~*