From 2d7c95fb701b4a8263b18c662c4e6993223229c3 Mon Sep 17 00:00:00 2001 From: Sonu Kapoor Date: Tue, 24 Mar 2020 22:54:54 +0200 Subject: [PATCH] fix(service-worker): prevent SW registration strategies from affecting app stabilization (#35870) Previously, some of the built-in ServiceWorker registration strategies, namely `registerWithDelay:` and `registerWhenStable:`, would register potentially long-running timeout, thus preventing the app from stabilizing before the timeouts expired. This was especially problematic for the `registerWhenStable:` strategy, which waits for the app to stabilize, because the strategy itself would prevent the app from stabilizing and thus the ServiceWorker would always be registered after the timeout. This commit fixes this by subscribing to the registration strategy observable outside the Angular zone, thus not affecting the app's stabilization. PR Close #35870 --- packages/service-worker/src/module.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/service-worker/src/module.ts b/packages/service-worker/src/module.ts index 85eef4f67c..d707a58e33 100644 --- a/packages/service-worker/src/module.ts +++ b/packages/service-worker/src/module.ts @@ -7,7 +7,7 @@ */ import {isPlatformBrowser} from '@angular/common'; -import {APP_INITIALIZER, ApplicationRef, InjectionToken, Injector, ModuleWithProviders, NgModule, PLATFORM_ID} from '@angular/core'; +import {APP_INITIALIZER, ApplicationRef, InjectionToken, Injector, ModuleWithProviders, NgModule, NgZone, PLATFORM_ID} from '@angular/core'; import {Observable, merge, of } from 'rxjs'; import {delay, filter, take} from 'rxjs/operators'; @@ -122,10 +122,15 @@ export function ngswAppInitializer( } // Don't return anything to avoid blocking the application until the SW is registered. + // Also, run outside the Angular zone to avoid preventing the app from stabilizing (especially + // given that some registration strategies wait for the app to stabilize). // Catch and log the error if SW registration fails to avoid uncaught rejection warning. - readyToRegister$.pipe(take(1)).subscribe( - () => navigator.serviceWorker.register(script, {scope: options.scope}) - .catch(err => console.error('Service worker registration failed with:', err))); + const ngZone = injector.get(NgZone); + ngZone.runOutsideAngular( + () => readyToRegister$.pipe(take(1)).subscribe( + () => + navigator.serviceWorker.register(script, {scope: options.scope}) + .catch(err => console.error('Service worker registration failed with:', err)))); }; return initializer; }