Service Worker 可以增强传统的 Web 发布模式,并使应用程序能够提供可与原生代码(它运行在你的操作系统和硬件层面)媲美的高可靠、高性能的用户体验。为 Angular 应用添加 Service Worker 是把应用转换成渐进式应用(PWA)的步骤之一。
简单来说,Service Worker 就是一段运行在 Web 浏览器中,并为应用管理缓存的脚本。
Service Worker 的功能就像一个网络代理。它们会拦截所有由应用发出的 HTTP 请求,并选择如何给出响应。比如,它们可以查询局部缓存,如果有缓存的响应数据,就用它做出响应。这种代理行为不会局限于通过程序调用 API(比如 fetch
)发起的请求,还包括 HTML 中对资源的引用,甚至对 index.html
的首次请求。基于 Service Worker 的缓存是完全可编程的,并且不依赖于服务端指定的那些控制缓存策略的头。
不像应用中的其它脚本(如 Angular 的应用包),Service Worker 在用户关闭浏览器页标签时仍然会被保留。下次浏览器加载本应用时,Service Worker 会首先加载,然后拦截加载本应用时的对每一项资源的请求。如果这个 Service Worker 就是为此而设计的,它就能完全满足应用加载时的需求,而不需要依赖网络。
即使在快速可靠的网络中,往返延迟也可能在加载应用程序时产生显著的延迟。使用 Service Worker 来减少对网络的依赖可以显著改善用户体验。
作为单页面应用,Angular 应用可以受益于 Service Worker 的优势。从 Angular v5.0.0 开始,Angular 提供了一份 Service Worker 的实现。Angular 开发人员可以利用 Service Worker,并受益于其增强的可靠性和性能,而无需再针对底层 API 写代码。
Angular 的 Service Worker 的设计目标是优化那些使用慢速、不可靠网络的最终用户的体验,同时还要尽可能减小提供过期内容的风险。
为了达成此目标,Angular Service Worker 的行为遵循下列设计原则:
要支持这些行为,Angular 的 Service Worker 会从服务器上下载一个 manifest
文件。 这个 manifest
文件(不同于 web 应用的 manifest)描述要缓存的资源,并包含每个文件内容的哈希值。 当发布了应用的一个新版本时,manifest
的内容就会改变,通知 Service Worker 应该下载并缓存应用的一个新版本了。 这个 manifest 是从 CLI 生成的一个名叫 ngsw-config.json
的文件中生成的。
安装 Angular 的 Service Worker 就像引入一个 NgModule
一样简单。除了使用浏览器注册 Angular 的 Service Worker 之外,还要制作一些可供注入的服务,它们可以与 Service Worker 交互,并控制它。比如,应用可以要求当新的更新已经就绪时通知自己,或要求 Service Worker 检查服务器,看是否有可用的更新。
要使用 Angular Service Worker 的所有功能,请使用最新版本的 Angular 和 Angular CLI。
要注册 Service Worker,必须通过 HTTPS 而非 HTTP 访问该应用程序。浏览器会忽略通过不安全连接访问的页面上的 Service Worker。原因是 Service Worker 非常强大,因此需要格外小心,以确保 Service Worker 的脚本未被篡改。
这条规则有一个例外:为了方便本地开发,当访问 localhost
上的应用时,浏览器不要求安全连接。
要从 Angular Service Worker 中受益,你的应用必须在支持 Service Worker 的 Web 浏览器中运行。当前,最新版本的 Chrome,Firefox,Edge,Safari,Opera,UC 浏览器(Android 版)和 Samsung Internet 支持 Service Worker。而 IE 和 Opera Mini 等浏览器不支持 Service Worker。
如果用户通过不支持 Service Worker 的浏览器访问你的应用程序,则该 Service Worker 不会注册,并且不会发生相关行为,比如脱机缓存管理和推送通知。进一步来说:
ngsw.json
清单文件。SwUpdate.checkForUpdate()
,会返回被拒绝的承诺(Promise)SwUpdate.available
)的可观察事件不会触发强烈建议你确保即使在浏览器中没有 Service Worker 支持的情况下,你的应用也可以正常运行。尽管不受支持的浏览器会忽略 Service Worker 缓存,但如果应用程序尝试与 Service Worker 进行交互,它将仍然会报告错误。比如,调用 SwUpdate.checkForUpdate()
将返回被拒绝的承诺。为避免此类错误,你可以使用 SwUpdate.isEnabled()
检查是否启用了 Angular Service Worker。