diff --git a/aio/content/guide/service-worker-config.md b/aio/content/guide/service-worker-config.md index c2273b28ca..1cb77cfb56 100644 --- a/aio/content/guide/service-worker-config.md +++ b/aio/content/guide/service-worker-config.md @@ -218,3 +218,15 @@ If the field is omitted, it defaults to: '!/**/*__*/**', // Exclude URLs containing `__` in any other segment. ] ``` + +## `register options` + + + You can pass some options to the `register()` method. +- enabled: optional parameter, by default is true, if enabled is false, the module will behave like the browser not support service worker, and service worker will not be registered. +- scope: optional parameter, to specify the subset of your content that you want the service worker to control. +- registrationStrategy: optional parameter, specify a strategy that determines when to register the service worker, the available options are: + - registerWhenStable: this is the default behavior, the service worker will register when the application is stable (no microTasks or macroTasks remain). + - registerImmediately: register immediately without waiting the application to become stable. + - registerDelay:timeout : register after the timeout period, `timeout` is the number of milliseconds to delay registration. For example `registerDelay:5000` would register the service worker after 5 seconds. If the number of `timeout` is not given (`registerDelay`), by default, `timeout` will be `0`, but it is not equal to `registerImmediately`, it will still run a `setTimeout(register, 0)` to wait all `microTasks` to finish then perform registration of the service worker. + - A factory to get Observable : you can also specify a factory which returns an Observable, the service worker will be registered the first time that a value is emitted by the Observable. \ No newline at end of file diff --git a/aio/content/guide/service-worker-getting-started.md b/aio/content/guide/service-worker-getting-started.md index e622f89530..5d36fdf3cf 100644 --- a/aio/content/guide/service-worker-getting-started.md +++ b/aio/content/guide/service-worker-getting-started.md @@ -1,7 +1,7 @@ # Getting started with service workers -This document explains how to enable Angular service worker support in projects that you created with the [Angular CLI](cli). It then uses a simple example to show you a service worker in action, demonstrating loading and basic caching. +This document explains how to enable Angular service worker support in projects that you created with the [Angular CLI](cli). It then uses a simple example to show you a service worker in action, demonstrating loading and basic caching. #### Prerequisites @@ -10,26 +10,26 @@ A basic understanding of the information in [Introduction to Angular service wor ## Adding a service worker to your project -To set up the Angular service worker in your project, use the CLI command `ng add @angular/pwa`. It takes care of configuring your app to use service workers by adding the `service-worker` package along +To set up the Angular service worker in your project, use the CLI command `ng add @angular/pwa`. It takes care of configuring your app to use service workers by adding the `service-worker` package along with setting up the necessary support files. ```sh -ng add @angular/pwa --project *project-name* +ng add @angular/pwa --project *project-name* ``` The above command completes the following actions: -1. Adds the `@angular/service-worker` package to your project. +1. Adds the `@angular/service-worker` package to your project. 2. Enables service worker build support in the CLI. 3. Imports and registers the service worker in the app module. 4. Updates the `index.html` file: * Includes a link to add the `manifest.json` file. * Adds meta tags for `theme-color`. 5. Installs icon files to support the installed Progressive Web App (PWA). -6. Creates the service worker configuration file called [`ngsw-config.json`](/guide/service-worker-config), which specifies the caching behaviors and other settings. +6. Creates the service worker configuration file called [`ngsw-config.json`](/guide/service-worker-config), which specifies the caching behaviors and other settings. - Now, build the project: + Now, build the project: ```sh ng build --prod @@ -40,8 +40,8 @@ The CLI project is now set up to use the Angular service worker. ## Service worker in action: a tour -This section demonstrates a service worker in action, -using an example application. +This section demonstrates a service worker in action, +using an example application. ### Serving with `http-server` @@ -61,7 +61,7 @@ With the server running, you can point your browser at http://localhost:8080/. Y ### Simulating a network issue -To simulate a network issue, disable network interaction for your application. In Chrome: +To simulate a network issue, disable network interaction for your application. In Chrome: 1. Select **Tools** > **Developer Tools** (from the Chrome menu located at the top right corner). 2. Go to the **Network tab**. @@ -73,9 +73,9 @@ To simulate a network issue, disable network interaction for your application. I Now the app has no access to network interaction. -For applications that do not use the Angular service worker, refreshing now would display Chrome's Internet disconnected page that says "There is no Internet connection". +For applications that do not use the Angular service worker, refreshing now would display Chrome's Internet disconnected page that says "There is no Internet connection". -With the addition of an Angular service worker, the application behavior changes. On a refresh, the page loads normally. +With the addition of an Angular service worker, the application behavior changes. On a refresh, the page loads normally. If you look at the Network tab, you can verify that the service worker is active. @@ -107,12 +107,12 @@ Pay attention to two key points: ### Making changes to your application -Now that you've seen how service workers cache your application, the -next step is understanding how updates work. +Now that you've seen how service workers cache your application, the +next step is understanding how updates work. 1. If you're testing in an incognito window, open a second blank tab. This will keep the incognito and the cache state alive during your test. -2. Close the application tab, but not the window. This should also close the Developer Tools. +2. Close the application tab, but not the window. This should also close the Developer Tools. 3. Shut down `http-server`. @@ -156,4 +156,4 @@ The service worker installed the updated version of your app *in the background* ## More on Angular service workers You may also be interested in the following: -* [Communicating with service workers](guide/service-worker-communications). +* [Communicating with service workers](guide/service-worker-communications). \ No newline at end of file diff --git a/packages/service-worker/src/module.ts b/packages/service-worker/src/module.ts index ddcd9102a4..5d07f9e88e 100644 --- a/packages/service-worker/src/module.ts +++ b/packages/service-worker/src/module.ts @@ -8,6 +8,7 @@ import {isPlatformBrowser} from '@angular/common'; import {APP_INITIALIZER, ApplicationRef, InjectionToken, Injector, ModuleWithProviders, NgModule, PLATFORM_ID} from '@angular/core'; +import {Observable} from 'rxjs'; import {filter, take} from 'rxjs/operators'; import {NgswCommChannel} from './low_level'; @@ -41,6 +42,8 @@ export abstract class SwRegistrationOptions { * [ServiceWorkerContainer#register()](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register). */ scope?: string; + + registrationStrategy?: (() => Observable)|string; } export const SCRIPT = new InjectionToken('NGSW_REGISTER_SCRIPT'); @@ -68,7 +71,33 @@ export function ngswAppInitializer( // Don't return the Promise, as that will block the application until the SW is registered, and // cause a crash if the SW registration fails. - whenStable.then(() => navigator.serviceWorker.register(script, {scope: options.scope})); + if (typeof options.registrationStrategy === 'function') { + const observable = options.registrationStrategy(); + const subscription = observable.subscribe(() => { + navigator.serviceWorker.register(script, {scope: options.scope}); + subscription.unsubscribe(); + }); + } else { + const registrationStrategy = typeof options.registrationStrategy === 'string' ? + options.registrationStrategy : + 'registerWhenStable'; + if (registrationStrategy === 'registerWhenStable') { + whenStable.then(() => navigator.serviceWorker.register(script, {scope: options.scope})); + } else if (registrationStrategy === 'registerImmediately') { + navigator.serviceWorker.register(script, {scope: options.scope}); + } else if (registrationStrategy.indexOf('registerDelay') !== -1) { + const split = registrationStrategy.split(':'); + const delayStr = split.length > 1 ? split[1] : undefined; + const delay = Number(delayStr); + setTimeout( + () => navigator.serviceWorker.register(script, {scope: options.scope}), + typeof delay === 'number' ? delay : 0); + } else { + // wrong strategy + throw new Error( + `Unknown service worker registration strategy: ${options.registrationStrategy}`); + } + } }; return initializer; } diff --git a/tools/public_api_guard/service-worker/service-worker.d.ts b/tools/public_api_guard/service-worker/service-worker.d.ts index 80eddf9878..1ecb0bf761 100644 --- a/tools/public_api_guard/service-worker/service-worker.d.ts +++ b/tools/public_api_guard/service-worker/service-worker.d.ts @@ -21,6 +21,7 @@ export declare class SwPush { export declare abstract class SwRegistrationOptions { enabled?: boolean; + registrationStrategy?: (() => Observable) | string; scope?: string; }