使用 Service Worker

此 Codelab 介绍了如何在 Web 应用中注册 Service Worker,并使用 Chrome DevTools 观察其行为。此外,还介绍了在处理 Service Worker 时可能有用的一些调试技术。

熟悉示例项目

示例项目中与此 Codelab 最相关的文件包括:

  • register-sw.js 最初为空,但其中包含用于注册 Service Worker 的代码。它已通过项目的 index.html 内的 <script> 标记加载。
  • service-worker.js 同样为空。该文件将包含此项目的 Service Worker。

添加 Service Worker 注册代码

系统不会使用 Service Worker(即使是空的 Service Worker,比如当前的 service-worker.js 文件),除非先注册该 Service Worker。您可以通过调用以下方法来实现此目的:

navigator.serviceWorker.register(
  '/service-worker.js'
)

放在 register-sw.js 文件中。

不过,在添加该代码之前,您需要考虑以下几点。

首先,并非所有浏览器都支持 Service Worker。对于不能自动更新的旧版浏览器来说尤其如此。因此,最佳做法是先检查是否支持 navigator.serviceWorker,然后有条件地调用 navigator.serviceWorker.register()

其次,当您注册 Service Worker 时,浏览器会运行 service-worker.js 文件中的代码,并且可能会开始下载网址以填充缓存,具体取决于 Service Worker 的 installactivate 事件处理程序中的代码。

运行其他代码并下载资源可能会占用浏览器用来显示当前网页的宝贵资源。为了避免这种干扰,最好将 Service Worker 的注册延迟到浏览器完成当前页面的渲染。大致估算此值的一种便捷方法是等待 window.load 事件被触发。

综合这两点,将以下通用 Service Worker 注册代码添加到 register-sw.js 文件中:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js');
  });
}

添加一些 Service Worker 日志记录代码

通常,在 service-worker.js 文件中存储 Service Worker 实现的所有逻辑。您可以结合使用 Service Worker 生命周期事件Cache Storage API 以及 Web 应用网络流量方面的知识,创建精心设计的 Service Worker,以准备好处理 Web 应用的所有请求。

但...这些内容仅供日后学习。在此阶段,重点是观察各种 Service Worker 事件,并熟练使用 Chrome 的开发者工具来调试 Service Worker 的状态。

为此,请将以下代码添加到 service-worker.js,这样会将消息记录到开发者工具控制台中,以响应各种事件(但别做其他事情):

self.addEventListener('install', (event) => {
  console.log('Inside the install handler:', event);
});

self.addEventListener('activate', (event) => {
  console.log('Inside the activate handler:', event);
});

self.addEventListener(fetch, (event) => {
  console.log('Inside the fetch handler:', event);
});

熟悉 DevTools 中的 Service Workers 面板

现在,您已将代码添加到 register-sw.jsservice-worker.js 文件中,是时候访问示例项目的 Live 版本并观察 Service Worker 的运行了。

  • 如需预览网站,请按查看应用,然后按全屏 全屏
  • 按 `Ctrl+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
  • 点击控制台标签页。

您应该会看到类似于以下日志消息的内容,其中显示了 Service Worker 已安装并激活:

显示 Service Worker 已安装并激活。

然后,访问 Applications 标签页,并选择 Service Workers 面板。 您应看到类似下图的内容:

在 Service Worker 面板中显示 Service Worker 详细信息。

这样您就可以知道 Web 应用 solar-donkey.glitch.me 有一个源网址为 service-worker.js 的 Service Worker,且该 Service Worker 当前已激活且正在运行。它还会告诉您当前有一个客户端(打开的标签页)由 Service Worker 控制。

您可以使用此面板上的链接(例如 Unregisterstop)对当前注册的 Service Worker 进行更改,以便进行调试。

触发 Service Worker 更新流程

使用 Service Worker 进行开发时,需要理解的一个关键概念是更新流程

在您的用户访问注册 Service Worker 的 Web 应用后,他们最终将获得其本地浏览器中安装的当前 service-worker.js 副本的代码。但是,如果您更新存储在网络服务器上的 service-worker.js 版本,会发生什么情况?

当重复访问者返回到 Service Worker 范围内的网址时,浏览器将自动请求最新的 service-worker.js 并检查是否存在任何变化。如果 Service Worker 脚本中的任何内容不同,则新的 Service Worker 将有机会安装、激活并最终控制它。

您可以返回到项目的代码编辑器并对代码进行任何更改,以模拟此更新流程。一种简单的更改是

self.addEventListener('install', (event) => {
  console.log('Inside the install handler:', event);
});

通过

self.addEventListener('install', (event) => {
  console.log('Inside the UPDATED install handler:', event);
});

完成上述更改后,返回到示例应用的 Live 版本,并在开发者工具的“Application”标签页仍打开的情况下重新加载页面。您应该会看到如下内容:

显示已安装的两个 Service Worker 版本。

这表明此时安装了两个版本的 Service Worker。之前的版本(已被激活)正在运行且由当前页面控制。下面列出了 Service Worker 的更新版本。它处于 waiting 状态,并会一直等待,直到由旧 Service Worker 控制的所有打开的标签页关闭。

此默认行为可确保,如果新 Service Worker 在行为上与旧 Service Worker 之间存在根本性区别(例如,fetch 处理程序响应的资源与旧版本的 Web 应用不兼容),则在用户关闭 Web 应用的所有先前实例之前,该默认行为不会生效。

总结

现在,您应该可以自如地使用 Chrome 的开发者工具注册 Service Worker 和观察 Service Worker 的行为。

现在,您已处于良好状态,可以开始实现缓存策略,以及有助于 Web 应用快速可靠地加载的所有出色功能。