当前位置: 首页 > Web前端 > HTML5

Angular服务端渲染应用中常见的内存泄漏问题

时间:2023-04-04 23:54:17 HTML5

考虑以下Angular代码:import{Injectable,NgZone}from"@angular/core";import{interval}from"rxjs";@Injectable()exportclassLocationService{constructor(ngZone:NgZone){ngZone.runOutsideAngular(()=>interval(1000).subscribe(()=>{...}));}}这段代码不会影响应用的稳定性,但是如果应用在服务器上被销毁,传递给订阅的回调会继续被调用。服务器上应用程序的每次启动都会不时地留下一个工件。这是一个潜在的内存泄漏点。这种内存泄漏风险可以通过使用ngOnDestoroy挂钩来解决。此挂钩适用于组件和服务。我们需要保存interval返回的订阅,并在服务销毁时终止订阅。取消订阅有很多技巧,这里举一个例子:私人订阅:订阅;constructor(ngZone:NgZone){this.subscription=ngZone.runOutsideAngular(()=>interval(1000).subscribe(()=>{}));}ngOnDestroy():void{this.subscription.unsubscribe();}}屏幕闪烁问题用户浏览器显示从服务器渲染返回的页面,一瞬间出现白屏,闪烁片刻,然后应用程序开始运行,一切似乎都正常。闪烁的原因是Angular不知道如何重用它在服务器上成功呈现的内容。在客户端环境中,它从根元素中剥离所有HTML并重新开始绘制。闪烁问题可以抽象为以下步骤:对正在发生的事情的非常简单的解释:(1)用户访问应用程序(或刷新)(2)服务器在服务器中构建html(3)它被发送到用户的浏览器服务器端(4)Angular重新创建应用程序(就好像它是一个常规的非Angular通用应用程序)(5)当上述四个步骤发生时,用户会看到一个闪烁的屏幕。代码如下://你可以通过添加来看到这个://你应该在服务器中看到一个控制台日志//`RunningontheserverwithappId=my-app-id`//然后你会看到在浏览器控制台中类似于//`RunningonthebrowserwithappId=my-app-id`exportclassAppModule{constructor(@Inject(PLATFORM_ID)privateplatformId:Object,@Inject(APP_ID)privateappId:string){const平台=isPlatformBrowser(this.platformId)?'在浏览器中':'在服务器上';console.log(`Running${platform}withappId=${this.appId}`);}}无法通过API终止渲染什么时候需要手动终止服务端渲染?始终明确渲染应用的时间点发生在应用applicationRef.isStable返回true时,参考如下代码:https://github.com/angular/an...function_render(platform:PlatformRef,moduleRefPromise:Promise>):Promise{returnmoduleRefPromise.then((moduleRef)=>{consttransitionId=moduleRef.injector.get(?TRANSITION_ID,null);if(!transitionId){扔新错误(`renderModule[Factory]()需要使用BrowserModule.withServerTransition()来确保服务器呈现的应用程序可以正确引导到客户端应用程序中。`);constapplicationRef:ApplicationRef=moduleRef.injector.get(ApplicationRef);returnapplicationRef.isStable.pipe((first((isStable:boolean)=>isStable))).toPromise().then(()=>{constplatformState=platform.injector.get(PlatformState);...