# Angular 的 Service Worker 简介

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 应用可以受益于 Service Worker 的优势。从版本 5.0.0 开始,Angular 提供了一份 Service Worker 的实现。Angular 开发人员可以利用 Service Worker,并受益于其增强的可靠性和性能,而无需再针对底层 API 写代码。

Angular 的 Service Worker 的设计目标是优化那些使用慢速、不可靠网络的最终用户的体验,同时还要尽可能减小提供过期内容的风险。

为了达成此目标,Angular Service Worker 的行为遵循下列设计原则:

  • 像安装原生应用一样缓存应用。该应用作为整体被缓存,它的所有文件作为整体进行更新。

  • 正在运行的应用使用所有文件的同一版本继续运行。不要突然开始接收来自新版本的、可能不兼容的缓存文件。

  • 当用户刷新本应用时,他们会看到最新的被完全缓存的版本。新的页标签中会加载最新的缓存代码。

  • 在更改发布之后,相对较快的在后台进行更新。在一次完整的更新完成之前,仍然使用应用的上一个版本。

  • 只要有可能,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 不会注册,并且不会发生相关行为,比如脱机缓存管理和推送通知。进一步来说:

  • 浏览器不会下载 Service Worker 脚本和 ngsw.json清单文件。

  • 主动尝试与 Service Worker 进行交互,比如调用 SwUpdate.checkForUpdate(),会返回被拒绝的承诺(Promise)

  • 相关服务(比如 SwUpdate.available)的可观察事件不会触发

强烈建议你确保即使在浏览器中没有 Service Worker 支持的情况下,你的应用也可以正常运行。尽管不受支持的浏览器会忽略 Service Worker 缓存,但如果应用程序尝试与 Service Worker 进行交互,它将仍然会报告错误。比如,调用 SwUpdate.checkForUpdate()将返回被拒绝的 Promise 。为避免此类错误,你可以使用 SwUpdate.isEnabled()检查是否启用了 Angular Service Worker。

要了解关于其它支持 Service Worker 的浏览器的更多信息,请参阅 Can I Use 页面和 MDN 文档

# 相关资源

本节中的其余文章专门针对 Service Worker 的 Angular 实现。

  • 应用外壳

  • 与 Service Worker 通讯 .

  • Service Worker 通知

  • 生产环境下的 Service Worker

  • Service Worker 配置

要了解更多关于 Service Worker 的普遍性信息,参阅 Service Worker 简介

要了解关于浏览器支持度的更多信息,参阅 Service Worker 简介 中的浏览器支持部分、Jake Archibald 写的Serviceworker 好了吗?和 Can I Use

关于其它建议和范例,请参阅:

  • 使用 Angular Service Worker 进行预缓存

  • 使用 Angular CLI 创建 PWA

# 下一步

要开始使用 Angular service Worker,参阅 Service Worker 快速上手

Last Updated: 5/5/2023, 8:48:21 AM