Angular Universal 应用避免 SSR hang 的一些指导方针
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Angular Universal 应用避免 SSR hang 的一些指导方针相关的知识,希望对你有一定的参考价值。
当某些异步任务永远挂起时,Angular SSR 渲染可能永远不会完成,例如对后端 API 的 http 调用。
目前 Spartacus SSR 实现里,已经采取了一些措施来改善渲染挂起时的监控体验
:
我们添加了配置 SsrOptimizationOptions.maxRenderTime
.
在 maxRenderTime 时间之后,我们登录控制台,能看到显示渲染时间过长并且可能挂起的提示消息,但我们对此无能为力。
理想情况下,我们应该尽可能避免 render 进程出现 hang 的情况。
首先,最好调查一下 SSR 中出现 never-ending
的异步操作的最常见原因是什么,然后尝试阻止它们。
一种合理的猜测是,在大多数情况下,这是由于一个永不响应的 HTTP API 调用造成的。 如果情况确实如此,在 SSR 模式下,我们可以为所有 API 调用引入通用的 http 超时,因此它们最终会返回控制权给 SSR 服务器,因此 SSR 服务器可以继续进行其他请求的响应工作。
Angular Universal 的一个局限就在于,无法以编程方式中止挂起的渲染并释放分配的资源。
一种解决方案是,我们可以引入一个 Angular HTTP_INTERCEPTOR,它可以使长时间未决的网络请求超时,因此在服务器端启动的应用程序的生命周期更短。
换句话说:因此 SSR 渲染不会因为等待来自网络的缓慢 API 响应而“挂起”。 但是,这可能需要在应用程序代码甚至 SSR 代码中添加额外的逻辑,这样此类格式错误的渲染(基于不完整的数据)不会在 SSR 响应中返回。 在这种情况下,最好回退到具有无缓存标头的 CSR 应用程序,而不是允许发送格式错误的呈现 html 作为响应(并可能由 CDN 缓存)。
下面是一个具体的例子:
import NgModule from @angular/core;
import BrowserModule from @angular/platform-browser;
import HttpClientModule, HTTP_INTERCEPTORS from @angular/common/http;
import RequestTimeoutHttpInterceptor, DEFAULT_TIMEOUT from ./interceptors;
import AppComponent from ./app.component;
@NgModule(
imports: [
BrowserModule,
HttpClientModule,
],
declarations: [
AppComponent,
],
providers: [
provide: HTTP_INTERCEPTORS, useClass: RequestTimeoutHttpInterceptor, multi: true ,
provide: DEFAULT_TIMEOUT, useValue: 5000 ,
],
bootstrap: [AppComponent]
)
export class AppModule
import Injectable, InjectionToken, Inject from @angular/core;
import HttpInterceptor, HttpHandler, HttpRequest from @angular/common/http;
import empty, TimeoutError from rxjs;
import timeout, catchError from rxjs/operators;
export const DEFAULT_TIMEOUT = new InjectionToken<number>(defaultTimeout);
@Injectable(
providedIn: root
)
export class RequestTimeoutHttpInterceptor implements HttpInterceptor
constructor(
@Inject(DEFAULT_TIMEOUT) protected defaultTimeout: number,
)
intercept(req: HttpRequest<any>, next: HttpHandler)
const modified = req.clone(
setHeaders: X-Request-Timeout: `$this.defaultTimeout`
);
return next.handle(modified).pipe(
timeout(this.defaultTimeout),
catchError(err =>
if (err instanceof TimeoutError)
console.error(Timeout has occurred, req.url);
return empty();
)
);
以上是关于Angular Universal 应用避免 SSR hang 的一些指导方针的主要内容,如果未能解决你的问题,请参考以下文章
使用 Angular Universal 进行服务器端渲染的防御性编程思路
从 Angular Universal 应用程序中的 Express JS 获取值