Skip to content

Commit

Permalink
fix(service-worker): prevent SW registration strategies from affectin…
Browse files Browse the repository at this point in the history
…g app stabilization (#35870)

Previously, some of the built-in ServiceWorker registration strategies,
namely `registerWithDelay:<timeout>` and `registerWhenStable:<timeout>`,
would register potentially long-running timeout, thus preventing the app
from stabilizing before the timeouts expired. This was especially
problematic for the `registerWhenStable:<timeout>` 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
  • Loading branch information
sonukapoor authored and alxhub committed Mar 27, 2020
1 parent 29e8a64 commit 2d7c95f
Showing 1 changed file with 9 additions and 4 deletions.
13 changes: 9 additions & 4 deletions packages/service-worker/src/module.ts
Expand Up @@ -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';

Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 2d7c95f

Please sign in to comment.