使用 Service Worker

此 Codelab 介绍了如何在 Web 应用内注册 Service Worker,以及如何使用 Chrome 开发者工具观察其行为。此外,还介绍了一些在处理 Service Worker 时可能很有用的调试方法。

熟悉示例项目

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

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

添加 Service Worker 注册代码

除非先注册 Service Worker,否则系统不会使用它(即使是空的,例如当前的 service-worker.js 文件)。为此,您可以调用以下函数:

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);
});

熟悉开发者工具中的 Service Workers 面板

现在,您已将代码添加到 register-sw.jsservice-worker.js 文件中,接下来可以访问示例项目的 Live 版本,并观察 Service Worker 的实际运用了。

  • 如需预览网站,请按查看应用,然后按全屏 全屏
  • 按 `Control+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 控制。

您可以使用此面板上的链接(如 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 版本,然后在“开发者工具应用”标签页仍然打开的情况下重新加载页面。您应该会看到如下内容:

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

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

此默认行为可确保,如果新 Service Worker 在行为上与旧 Service Worker 存在根本性差异(例如,使用与旧版 Web 应用不兼容的资源进行响应的 fetch 处理程序),则只有在用户关闭所有先前 Web 应用实例后,新 Service Worker 才能生效。

总结内容

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

您现在就可以开始实施缓存策略,以及有助于 Web 应用可靠且快速地加载的所有实用功能。