Skip to content

Commit

Permalink
docs: Migrate Service Worker to Standalone (#51687)
Browse files Browse the repository at this point in the history
Although there are several pages, only `service-worker-getting-started.md` has an example.
That example code was migrated.

Worked around the few references to NgModule.

Other changes as follows:

**Revised "Getting Started"**

The original service worker example page (`service-worker-getting-started.md`) is full of holes! I don’t know how anyone got this working just by following this page

- it doesn’t tell you where to get the example (and it isn’t generated by AIO)
- it doesn’t tell you that ng serve doesn’t support service worker apps
- it mentions http-server in passing but not what that is or where to get it.
- several commands tell you to supply the “project-name” but (a) it doesn’t tell you how to find that name and (b) you never actually have to provide a name at all. That includes on the command that gets http-server going.

**Hid section on `ngsw-config` tool**

Hid the discussion of the `ngsw-config` tool in `service-worker-config.md` because
(a) the command invoke it didn't seem to work and (b) it referenced `<project-name>`
without explaining what that is or where to find it.

Left the hidden text in the page in case someone wants to do something about this.

Meanwhile, you seem to be able to edit the `ngsw-config.json` and then rebuild.
That should suffice.

**Disabled E2E**

The AIO CI will no longer attempt to run the (thin) E2E tests.

These tests could lightly test the app with the dev server but couldn't test the Service Worker aspects; that would require launching the app with something other than `ng serve` and the AIO CI is not set up for that.

The existing tests appeared to pass when run locally with the dev server.
However, only one of them actually ran; test runner reported.
"There were tests whose specified size is too big."

Decided to bypass E2E testing of this project for now.

PR Close #51687
  • Loading branch information
wardbell authored and pkozlowski-opensource committed Sep 19, 2023
1 parent 0b3e6a4 commit 9f3b549
Show file tree
Hide file tree
Showing 18 changed files with 97 additions and 93 deletions.
2 changes: 1 addition & 1 deletion aio/content/examples/examples.bzl
Expand Up @@ -88,7 +88,7 @@ EXAMPLES = {
"rx-library": {"stackblitz": True, "zip": True},
"schematics-for-libraries": {"stackblitz": False, "zip": True},
"security": {"stackblitz": True, "zip": True},
"service-worker-getting-started": {"stackblitz": False, "zip": False},
"service-worker-getting-started": {"stackblitz": False, "zip": True},
"setup": {"stackblitz": False, "zip": False},
"structural-directives": {"stackblitz": True, "zip": True},
"styleguide": {"stackblitz": False, "zip": False},
Expand Down
Expand Up @@ -4,4 +4,5 @@ package(default_visibility = ["//visibility:public"])

docs_example(
name = "service-worker-getting-started",
test = False,
)

This file was deleted.

Expand Up @@ -12,10 +12,10 @@ <h1>
<h2>Here are some links to help you start: </h2>
<ul>
<li>
<h2><a target="_blank" rel="noopener" href="https://angular.io/service-worker-intro">Angular Service Worker Intro</a></h2>
<h2><a target="_blank" rel="noopener" href="https://angular.io/guide/service-worker-intro">Angular Service Worker Intro</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial/tour-of-heroes">Tour of Heroes</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
Expand All @@ -24,4 +24,3 @@ <h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-c
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
</li>
</ul>

Expand Up @@ -2,6 +2,7 @@ import { Component } from '@angular/core';
import { SwUpdate } from '@angular/service-worker';

@Component({
standalone: true,
selector: 'app-root',
templateUrl: './app.component.html'
})
Expand Down

This file was deleted.

Expand Up @@ -3,7 +3,7 @@ import { SwUpdate } from '@angular/service-worker';
import { concat, interval } from 'rxjs';
import { first } from 'rxjs/operators';

@Injectable()
@Injectable({providedIn: 'root'})
export class CheckForUpdateService {

constructor(appRef: ApplicationRef, updates: SwUpdate) {
Expand Down
Expand Up @@ -4,7 +4,7 @@ import { SwUpdate } from '@angular/service-worker';
function notifyUser(message: string): void { }

// #docregion sw-unrecoverable-state
@Injectable()
@Injectable({providedIn: 'root'})
export class HandleUnrecoverableStateService {
constructor(updates: SwUpdate) {
updates.unrecoverable.subscribe(event => {
Expand Down
Expand Up @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { SwUpdate, VersionReadyEvent } from '@angular/service-worker';

// #docregion sw-update
@Injectable()
@Injectable({providedIn: 'root'})
export class LogUpdateService {

constructor(updates: SwUpdate) {
Expand Down
Expand Up @@ -10,7 +10,7 @@ function promptUser(event: VersionReadyEvent): boolean {
}

// #docregion sw-version-ready
@Injectable()
@Injectable({providedIn: 'root'})
export class PromptUpdateService {

constructor(swUpdate: SwUpdate) {
Expand Down
11 changes: 7 additions & 4 deletions aio/content/examples/service-worker-getting-started/src/main.ts
@@ -1,6 +1,9 @@
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { bootstrapApplication, provideProtractorTestingSupport } from '@angular/platform-browser';

import { AppModule } from './app/app.module';
import { AppComponent } from './app/app.component';

platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
bootstrapApplication(AppComponent, {
providers: [
provideProtractorTestingSupport(), // essential for e2e testing
]
});
@@ -0,0 +1,7 @@
{
"files": [
"!dist/",
"!**/*.d.ts",
"!**/src/**/*.js"
]
}
4 changes: 2 additions & 2 deletions aio/content/guide/service-worker-communications.md
@@ -1,6 +1,6 @@
# Service worker communication

Importing `ServiceWorkerModule` into your `AppModule` doesn't just register the service worker, it also provides a few services you can use to interact with the service worker and control the caching of your application.
Enabling service worker support does more than just register the service worker; it also provides services you can use to interact with the service worker and control the caching of your application.

## Prerequisites

Expand Down Expand Up @@ -48,7 +48,7 @@ The check might fail, which will cause a rejection of the `Promise`.

<div class="alert is-important">

In order to avoid negatively affecting the initial rendering of the page, `ServiceWorkerModule` waits for up to 30 seconds by default for the application to stabilize, before registering the ServiceWorker script.
In order to avoid negatively affecting the initial rendering of the page, by default the Angular service worker service waits for up to 30 seconds for the application to stabilize before registering the ServiceWorker script.
Constantly polling for updates, for example, with [setInterval()](https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) or RxJS' [interval()](https://rxjs.dev/api/index/function/interval), prevents the application from stabilizing and the ServiceWorker script is not registered with the browser until the 30 seconds upper limit is reached.

<div class="alert is-helpful">
Expand Down
12 changes: 9 additions & 3 deletions aio/content/guide/service-worker-config.md
Expand Up @@ -9,8 +9,13 @@ A basic understanding of the following:
* [Service worker overview](https://developer.chrome.com/docs/workbox/service-worker-overview/)
* [Service Worker in Production](guide/service-worker-devops)

The `ngsw-config.json` configuration file specifies which files and data URLs the Angular service worker should cache and how it should update the cached files and data.
The [Angular CLI](cli) processes the configuration file during `ng build`.
## Modifying the configuration

The `ngsw-config.json` JSON configuration file specifies which files and data URLs the Angular service worker should cache and how it should update the cached files and data.
The [Angular CLI](cli) processes this configuration file during `ng build`.

<!-- Does the following ngsw-config tool still work? Does not seem to. Not even clear what it does.
Manually, process it with the `ngsw-config` tool \(where `<project-name>` is the name of the project being built\):
<code-example format="shell" language="shell">
Expand All @@ -20,6 +25,7 @@ Manually, process it with the `ngsw-config` tool \(where `<project-name>` is the
</code-example>
The configuration file uses the JSON format.
-->
All file paths must begin with `/`, which corresponds to the deployment directory &mdash;usually `dist/<project-name>` in CLI projects.

<a id="glob-patterns"></a>
Expand Down Expand Up @@ -451,4 +457,4 @@ It is recommended that you use the default performance strategy whenever possibl

<!-- end links -->

@reviewed 2022-02-28
@reviewed 2023-09-06
4 changes: 2 additions & 2 deletions aio/content/guide/service-worker-devops.md
Expand Up @@ -33,7 +33,7 @@ Any time this version of `index.html` is served, the corresponding `bundle.js` m
For example, assume that the `startApp()` function is renamed to `runApp()` in both files.
In this scenario, it is not valid to serve the old `index.html`, which calls `startApp()`, along with the new bundle, which defines `runApp()`.

This file integrity is especially important when lazy loading modules.
This file integrity is especially important when lazy loading.
A JS bundle might reference many lazy chunks, and the filenames of the lazy chunks are unique to the particular build of the application.
If a running application at version `X` attempts to load a lazy chunk, but the server has already updated to version `X + 1`, the lazy loading operation fails.

Expand Down Expand Up @@ -354,4 +354,4 @@ You might also be interested in the following:

<!-- end links -->

@reviewed 2022-02-28
@reviewed 2023-09-06
66 changes: 52 additions & 14 deletions aio/content/guide/service-worker-getting-started.md
Expand Up @@ -7,30 +7,31 @@ It then uses an example to show you a service worker in action, demonstrating lo

A basic understanding of the information in [Introduction to Angular service workers](guide/service-worker-intro).

<a id="cli-command"></a>

## 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 application to use service workers by adding the `@angular/service-worker` package along
with setting up the necessary support files.
To set up the Angular service worker in your project, run the following CLI command.

<code-example format="shell" language="shell">

ng add @angular/pwa --project &lt;project-name&gt;
ng add @angular/pwa

</code-example>

The preceding command completes the following actions:
The CLI configures your application to use service workers with the following actions:

1. Adds the `@angular/service-worker` package to your project.
1. Enables service worker build support in the CLI.
1. Imports and registers the service worker in the application module.
1. Imports and registers the service worker with the application's root providers.
1. Updates the `index.html` file:
* Includes a link to add the `manifest.webmanifest` file
* Adds a meta tag for `theme-color`
1. Installs icon files to support the installed Progressive Web App \(PWA\).
1. Creates the service worker configuration file called [`ngsw-config.json`](guide/service-worker-config), which specifies the caching behaviors and other settings.
1. 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:

<code-example format="shell" language="shell">

Expand All @@ -45,9 +46,36 @@ The CLI project is now set up to use the Angular service worker.
This section demonstrates a service worker in action,
using an example application.

<div class="alert is-helpful">

To play along,
<live-example downloadOnly>download the example code</live-example>.

Unzip the download, change to that directory, and enter the following commands in a terminal window,

<code-example format="shell" language="shell">

npm install # install node packages
ng add @angular/pwa # setup to use service worker
ng build # build the app for production; code is in the /dist folder

</code-example>

The Angular development server (`ng serve`) doesn't support service worker applications.
The [`http-server package`](https://www.npmjs.com/package/http-server) from npm does.
You can run it without installing it like this:

<code-example format="shell" language="shell">

npx http-server -p 8080 -c-1 dist/

</code-example>

</div>

### Initial load

With the server running, point your browser at `http://localhost:8080`.
With the server running on port `8080`, point your browser at `http://localhost:8080`.
Your application should load normally.

<div class="alert is-helpful">
Expand Down Expand Up @@ -138,15 +166,15 @@ Make a change to the application, and watch the service worker install the updat
1. Close the application tab, but not the window.
This should also close the Developer Tools.

1. Shut down `http-server`.
1. Shut down `http-server` (Ctrl-c).
1. Open `src/app/app.component.html` for editing.
1. Change the text `Welcome to {{title}}!` to `Bienvenue à {{title}}!`.
1. Build and run the server again:

<code-example format="shell" language="shell">

ng build
http-server -p 8080 -c-1 dist/&lt;project-name&gt;
npx http-server -p 8080 -c-1 dist/

</code-example>

Expand All @@ -164,11 +192,21 @@ Now look at how the browser and service worker handle the updated application.
</div>

What went wrong?
Nothing, actually.
_Nothing, actually!_

The Angular service worker is doing its job and serving the version of the application that it has **installed**, even though there is an update available.
In the interest of speed, the service worker doesn't wait to check for updates before it serves the application that it has cached.

<br>

Look at the `http-server` logs to see the service worker requesting `/ngsw.json`.

<code-example format="shell" language="shell">

[2023-09-07T00:37:24.372Z] "GET /ngsw.json?ngsw-cache-bust=0.9365263935102124" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"

</code-example>

This is how the service worker checks for updates.

1. Refresh the page.
Expand All @@ -185,13 +223,13 @@ Now look at how the browser and service worker handle the updated application.

You might also be interested in the following:

* [App Shell](guide/app-shell)
* [Communicating with service workers](guide/service-worker-communications)
* [App Shell](guide/app-shell)

<!-- links -->

<!-- external links -->

<!-- end links -->

@reviewed 2022-02-28
@reviewed 2023-09-06
8 changes: 4 additions & 4 deletions aio/content/guide/service-worker-intro.md
Expand Up @@ -48,7 +48,7 @@ The file, called `ngsw.json` \(not to be confused with the [web app manifest](ht
When an update to the application is deployed, the contents of the manifest change, informing the service worker that a new version of the application should be downloaded and cached.
This manifest is generated from a CLI-generated configuration file called `ngsw-config.json`.

Installing the Angular service worker is as straightforward as including an `NgModule`.
Installing the Angular service worker is as straightforward as [running an Angular CLI command](guide/service-worker-getting-started#cli-command).
In addition to registering the Angular service worker with the browser, this also makes a few services available for injection which interact with the service worker and can be used to control it.
For example, an application can ask to be notified when a new update becomes available, or an application can ask the service worker to check the server for available updates.

Expand Down Expand Up @@ -86,11 +86,11 @@ To learn more about other browsers that are service worker ready, see the [Can I

The rest of the articles in this section specifically address the Angular implementation of service workers.

* [App Shell](guide/app-shell)
* [Service Worker Communication](guide/service-worker-communications)
* [Service Worker Notifications](guide/service-worker-notifications)
* [Service Worker in Production](guide/service-worker-devops)
* [Service Worker Configuration](guide/service-worker-config)
* [App Shell](guide/app-shell)

For more information about service workers in general, see [Service Workers: an Introduction](https://developers.google.com/web/fundamentals/primers/service-workers).

Expand All @@ -101,7 +101,7 @@ For additional recommendations and examples, see:
* [Precaching with Angular Service Worker](https://web.dev/precaching-with-the-angular-service-worker)
* [Creating a PWA with Angular CLI](https://web.dev/creating-pwa-with-angular-cli)

## Next steps
## Next step

To begin using Angular service workers, see [Getting Started with service workers](guide/service-worker-getting-started).

Expand All @@ -111,4 +111,4 @@ To begin using Angular service workers, see [Getting Started with service worker

<!-- end links -->

@reviewed 2022-02-28
@reviewed 2023-09-06

0 comments on commit 9f3b549

Please sign in to comment.