升级到Angular v14.x
版本后,发现刷新页面时会出现闪现(flickering)的情况,查看控制台,发现是重复请求的问题,即:服务端发起请求后,在客户端又重新发起了一次请求。
此问题在刚开始接触Angular Universal
时已经踩过坑,彼时是通过引入TransferHttpCacheModule
、BrowserTransferStateModule
、ServerTransferStateModule
解决的。然而,后两个module在新版本中却报Deprecated
错误:
Deprecated symbol used, consult docs for better alternative
官方文档中也显示:
Deprecated: no longer needed, you can inject the TransferState in an app without providing this module.
因此猜测,大概是要自行实现缓存逻辑了……
至于解决方案,直觉上是通过拦截器方式统一实现,因此,直接修改ApiRequestInterceptor
:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
if (httpRequest.method !== 'GET') {
return next.handle(httpRequest);
}
const key: StateKey<string> = makeStateKey<string>(`${httpRequest.url}?${httpRequest.params.toString()}`);
if (this.platform.isServer) {
return next.handle(httpRequest).pipe(
tap((event) => {
this.state.set(key, (<HttpResponse<any>>event).body);
})
);
} else {
const storedResponse = this.state.get<any>(key, null);
if (storedResponse) {
const response = new HttpResponse({ body: storedResponse, status: 200 });
this.state.remove(key);
return of(response);
} else {
return next.handle(httpRequest);
}
}
完整代码请参见:GitHub。
几个注意点:
- 缓存只针对
GET
请求; - 缓存只在服务端设置,客户端只进行读取;
- 尤其需要注意的,作为缓存的
key
需要考虑到请求参数,不能直接取httpRequest.url
,否则,不同参数的同一个API
客户端将读取错误。