mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
docs(service-worker): improve docs related to SwUpdate APIs (#46960)
This commit improves documentation related to recently improved or deprecated `SwUpdate` APIs in the following ways: - Update [check-for-update.service.ts][1] to make use of the return value of [SwUpdate#checkForUpdate()][2]. - Update [prompt-update.service.ts][3] to not call [SwUpdate#activateUpdate()][4] and just reload the page. - Update the [SwUpdate#activateUpdate()][4] API docs to explain that it is only useful if you want to update a client without reloading and that it can easily lead to version skew. - Update [a code-snippet][5] to no longer be [hard-coded][6]. [1]:9d9d05911d/aio/content/examples/service-worker-getting-started/src/app/check-for-update.service.ts (L16)[2]: https://angular.io/api/service-worker/SwUpdate#checkForUpdate [3]:9d9d05911d/aio/content/examples/service-worker-getting-started/src/app/prompt-update.service.ts (L15)[4]: https://angular.io/api/service-worker/SwUpdate#activateUpdate [5]:96c6139c9a/packages/service-worker/src/update.ts (L44-L54)[6]: https://angular.io/guide/docs-style-guide#hard-coded-snippets Fixes #43665 PR Close #46960
This commit is contained in:
parent
f8e78e3f9b
commit
c905da12e2
4 changed files with 66 additions and 28 deletions
|
|
@ -13,6 +13,13 @@ export class CheckForUpdateService {
|
|||
const everySixHours$ = interval(6 * 60 * 60 * 1000);
|
||||
const everySixHoursOnceAppIsStable$ = concat(appIsStable$, everySixHours$);
|
||||
|
||||
everySixHoursOnceAppIsStable$.subscribe(() => updates.checkForUpdate());
|
||||
everySixHoursOnceAppIsStable$.subscribe(async () => {
|
||||
try {
|
||||
const updateFound = await updates.checkForUpdate();
|
||||
console.log(updateFound ? 'A new version is available.' : 'Already on the latest version.');
|
||||
} catch (err) {
|
||||
console.error('Failed to check for updates:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,40 @@
|
|||
// #docplaster
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SwUpdate, UpdateAvailableEvent } from '@angular/service-worker';
|
||||
// #docregion sw-replicate-available
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
// #enddocregion sw-replicate-available
|
||||
import { SwUpdate, VersionReadyEvent } from '@angular/service-worker';
|
||||
|
||||
function promptUser(event: UpdateAvailableEvent): boolean {
|
||||
function promptUser(event: VersionReadyEvent): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
// #docregion sw-activate
|
||||
// #docregion sw-version-ready
|
||||
@Injectable()
|
||||
export class PromptUpdateService {
|
||||
|
||||
constructor(updates: SwUpdate) {
|
||||
updates.available.subscribe(event => {
|
||||
if (promptUser(event)) {
|
||||
updates.activateUpdate().then(() => document.location.reload());
|
||||
}
|
||||
});
|
||||
constructor(swUpdate: SwUpdate) {
|
||||
swUpdate.versionUpdates
|
||||
.pipe(filter((evt): evt is VersionReadyEvent => evt.type === 'VERSION_READY'))
|
||||
.subscribe(evt => {
|
||||
if (promptUser(evt)) {
|
||||
// Reload the page to update to the latest version.
|
||||
document.location.reload();
|
||||
}
|
||||
});
|
||||
// #enddocregion sw-version-ready
|
||||
// #docregion sw-replicate-available
|
||||
// ...
|
||||
const updatesAvailable = swUpdate.versionUpdates.pipe(
|
||||
filter((evt): evt is VersionReadyEvent => evt.type === 'VERSION_READY'),
|
||||
map(evt => ({
|
||||
type: 'UPDATE_AVAILABLE',
|
||||
current: evt.currentVersion,
|
||||
available: evt.latestVersion,
|
||||
})));
|
||||
// #enddocregion sw-replicate-available
|
||||
// #docregion sw-version-ready
|
||||
}
|
||||
|
||||
}
|
||||
// #enddocregion sw-activate
|
||||
// #enddocregion sw-version-ready
|
||||
|
|
|
|||
|
|
@ -64,16 +64,20 @@ Alternatively, you might want to define a different [registration strategy](api/
|
|||
|
||||
</div>
|
||||
|
||||
### Forcing update activation
|
||||
### Updating to the latest version
|
||||
|
||||
If the current tab needs to be updated to the latest application version immediately, it can ask to do so with the `activateUpdate()` method:
|
||||
You can update an existing tab to the latest version by reloading the page as soon as a new version is ready.
|
||||
To avoid disrupting the user's progress, it is generally a good idea to prompt the user and let them confirm that it is OK to reload the page and update to the latest version:
|
||||
|
||||
<code-example header="prompt-update.service.ts" path="service-worker-getting-started/src/app/prompt-update.service.ts" region="sw-activate"></code-example>
|
||||
<code-example header="prompt-update.service.ts" path="service-worker-getting-started/src/app/prompt-update.service.ts" region="sw-version-ready"></code-example>
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
Calling `activateUpdate()` without reloading the page could break lazy-loading in a currently running app, especially if the lazy-loaded chunks use filenames with hashes, which change every version.
|
||||
Therefore, it is recommended to reload the page once the promise returned by `activateUpdate()` is resolved.
|
||||
Calling {@link SwUpdate#activateUpdate SwUpdate#activateUpdate()} updates a tab to the latest version without reloading the page, but this could break the application.
|
||||
|
||||
Updating without reloading can create a version mismatch between the [application shell](guide/glossary#app-shell) and other page resources, such as [lazy-loaded chunks](guide/glossary#lazy-loading), whose filenames may change between versions.
|
||||
|
||||
You should only use `activateUpdate()`, if you are certain it is safe for your specific use case.
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -40,18 +40,11 @@ export class SwUpdate {
|
|||
*
|
||||
* @deprecated Use {@link versionUpdates} instead.
|
||||
*
|
||||
* The of behavior `available` can be rebuild by filtering for the `VersionReadyEvent`:
|
||||
* ```
|
||||
* import {filter, map} from 'rxjs/operators';
|
||||
* // ...
|
||||
* const updatesAvailable = swUpdate.versionUpdates.pipe(
|
||||
* filter((evt): evt is VersionReadyEvent => evt.type === 'VERSION_READY'),
|
||||
* map(evt => ({
|
||||
* type: 'UPDATE_AVAILABLE',
|
||||
* current: evt.currentVersion,
|
||||
* available: evt.latestVersion,
|
||||
* })));
|
||||
* ```
|
||||
* The behavior of `available` can be replicated by using `versionUpdates` by filtering for the
|
||||
* `VersionReadyEvent`:
|
||||
*
|
||||
* {@example service-worker-getting-started/src/app/prompt-update.service.ts
|
||||
* region='sw-replicate-available'}
|
||||
*/
|
||||
readonly available: Observable<UpdateAvailableEvent>;
|
||||
|
||||
|
|
@ -124,6 +117,20 @@ export class SwUpdate {
|
|||
* Updates the current client (i.e. browser tab) to the latest version that is ready for
|
||||
* activation.
|
||||
*
|
||||
* In most cases, you should not use this method and instead should update a client by reloading
|
||||
* the page.
|
||||
*
|
||||
* <div class="alert is-important">
|
||||
*
|
||||
* Updating a client without reloading can easily result in a broken application due to a version
|
||||
* mismatch between the [application shell](guide/glossary#app-shell) and other page resources,
|
||||
* such as [lazy-loaded chunks](guide/glossary#lazy-loading), whose filenames may change between
|
||||
* versions.
|
||||
*
|
||||
* Only use this method, if you are certain it is safe for your specific use case.
|
||||
*
|
||||
* </div>
|
||||
*
|
||||
* @returns a promise that
|
||||
* - resolves to `true` if an update was activated successfully
|
||||
* - resolves to `false` if no update was available (for example, the client was already on the
|
||||
|
|
|
|||
Loading…
Reference in a new issue