把 ServiceWorkerModule
导入到你的 AppModule
中不仅会注册 Service Worker,还会提供一些服务,让你能和 Service Worker 通讯,并控制你的应用缓存。
SwUpdate
服务让你能访问一些事件,这些事件会指出 Service Worker 何时发现并安装了可用的更新
SwUpdate
服务支持四个独立的操作:
versionUpdates
是 SwUpdate
的一个 Observable
属性,并且会发出四种事件类型:
事件类型 |
详情 |
---|---|
VersionDetectedEvent
|
当 Service Worker 在服务器上检测到应用程序的新版本并即将开始下载时发出。 |
NoNewVersionDetectedEvent
|
当 Service Worker 检查了服务器上应用程序的版本并且没有找到新版本时发出。 |
VersionReadyEvent
|
当有新版本的应用程序可供客户端激活时发出。它可用于通知用户可用的更新或提示他们刷新页面。 |
VersionInstallationFailedEvent
|
在新版本安装失败时发出。它可用于日志/监控目的。 |
@Injectable()
export class LogUpdateService {
constructor(updates: SwUpdate) {
updates.versionUpdates.subscribe(evt => {
switch (evt.type) {
case "VERSION_DETECTED":
console.log(`Downloading new app version: ${evt.version.hash}`);
break;
case "VERSION_READY":
console.log(`Current app version: ${evt.currentVersion.hash}`);
console.log(`New app version ready for use: ${evt.latestVersion.hash}`);
break;
case "VERSION_INSTALLATION_FAILED":
console.log(`Failed to install app version "${evt.version.hash}": ${evt.error}`);
break;
}
});
}
}
可以要求 Service Worker 检查是否有任何更新已经发布到了服务器上。Service Worker 会在初始化和每次导航请求(也就是用户导航到应用中的另一个地址)时检查更新。不过,如果你的站点更新非常频繁,或者需要按计划进行更新,你可能会选择手动检查更新。
通过调用 checkForUpdate()
方法来实现:
import { ApplicationRef, Injectable } from "@angular/core";
import { SwUpdate } from "@angular/service-worker";
import { concat, interval } from "rxjs";
import { first } from "rxjs/operators";
@Injectable()
export class CheckForUpdateService {
constructor(appRef: ApplicationRef, updates: SwUpdate) {
// Allow the app to stabilize first, before starting
// polling for updates with `interval()`.
const appIsStable$ = appRef.isStable.pipe(first(isStable => isStable === true));
const everySixHours$ = interval(6 * 60 * 60 * 1000);
const everySixHoursOnceAppIsStable$ = concat(appIsStable$, everySixHours$);
everySixHoursOnceAppIsStable$.subscribe(() => updates.checkForUpdate());
}
}
该方法返回一个用来表示检查更新已经成功完成的 Promise<boolean>
。这种检查可能会失败,它会导致此 Promise
被拒绝(reject)。
为了避免影响页面的首次渲染,在注册 ServiceWorker 脚本之前,
ServiceWorkerModule
默认会在应用程序达到稳定态之前等待最多 30 秒。如果不断轮询更新(比如调用 setInterval() 或 RxJS 的 interval())就会阻止应用程序达到稳定态,则直到 30 秒结束之前都不会往浏览器中注册 ServiceWorker 脚本。注意:
应用中所执行的各种轮询都会阻止它达到稳定态。可以通过在开始轮询更新之前先等应用达到稳定态来消除这种延迟,如上述例子所示。另外,你还可以为 ServiceWorker 定义不一样的 注册策略。
如果当前标签页需要立即更新到最新的应用版本,可以通过 activateUpdate()
方法来要求立即这么做:
@Injectable()
export class PromptUpdateService {
constructor(updates: SwUpdate) {
updates.available.subscribe(event => {
if (promptUser(event)) {
updates.activateUpdate().then(() => document.location.reload());
}
});
}
}
如果调用
activateUpdate()
而不刷新页面,可能会破坏正在运行的应用中的惰性加载模块,特别是如果惰性加载的模块文件名中使用了哈希时,就会改变每一个版本。所以,建议每当 activateUpdate()
返回的 Promise 被解析时,都刷新一次页面。
在某些情况下,Service Worker 用来为客户端提供服务的应用版本可能处于损坏状态,如果不重新加载整个页面,则无法恢复该状态。
比如,设想以下情形:
index.html
、main.<main-hash-1>.js
和 lazy-chunk.<lazy-hash-1>.js
。index.html
、main.<main-hash-2>.js
和 lazy-chunk.<lazy-hash-2>.js
。注意:
哈希值现在已经不同了,因为文件的内容已经改变)。服务器上不再提供旧版本。
旧版本在服务器上不再可用。
lazy-chunk.<lazy-hash-1>.js
浏览器可能决定从缓存中清退特定(或所有)资源,以便回收磁盘空间。
index.html
和 main.<main-hash-1>.js
)。
lazy-chunk.<lazy-hash-1>.js
。
lazy-chunk.<lazy-hash-2>.js
)。在上述情况下,Service Worker 将无法提供通常会被缓存的资产。该特定的应用程序版本已损坏,并且无法在不重新加载页面的情况下修复客户端的状态。在这种情况下,Service Worker 会通过发送 UnrecoverableStateEvent
事件来通知客户端。可以订阅 SwUpdate#unrecoverable
以得到通知并处理这些错误。
@Injectable()
export class HandleUnrecoverableStateService {
constructor(updates: SwUpdate) {
updates.unrecoverable.subscribe(event => {
notifyUser(
"An error occurred that we cannot recover from:n" +
event.reason +
"nnPlease reload the page."
);
});
}
}
Angular Universal:Angular 统一平台简介本指南讲的是Angular Universal(统一平台),一项在服务端运行 Angular 应用的技术。...
部署当你准备把Angular应用部署到远程服务器上时,有很多可选的部署方式。最简单的部署选项在完整部署应用之前,你可以先临时用...
AngularJS ng-model 指令ng-model 指令用于绑定应用程序数据到 HTML 控制器(input, select, textarea)的值。ng-model 指令ng-mod...
AngularJS ng-disabled 指令 AngularJS 参考手册AngularJS 实例禁用或启用输入框:禁用表单输入域: input type="checkbox" ng-mod...