使用 Service Worker

此代码实验室将向您展示如何从 Web 应用中注册服务工作线程,以及如何使用 Chrome DevTools 观察其行为。此外,还介绍了在处理 Service Worker 时可能有用的一些调试技术。

熟悉示例项目

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

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

添加 Service Worker 注册代码

除非先注册,否则系统不会使用服务工作线程(即使是空的服务工作线程,例如当前的 service-worker.js 文件)。您可以通过调用以下方法来实现此目的:

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

在您的 register-sw.js 文件中。

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

首先,并非所有浏览器都支持服务工作线程。对于不会自动更新的旧版浏览器,这一点尤为重要。因此,最佳实践是在检查是否支持 navigator.serviceWorker 后有条件地调用 navigator.serviceWorker.register()

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

运行额外的代码和下载资源可能会耗用浏览器原本可用于显示当前网页的重要资源。为避免此类干扰,最好延迟注册服务工作器,直到浏览器完成当前网页的呈现。若要近似地实现此操作,一种方便的方法是等待 window.load 事件触发。

将这两点结合起来,将以下通用服务工注册代码添加到 register-sw.js 文件中:

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

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

service-worker.js 文件通常是服务工件实现的所有逻辑所在的位置。您可以结合使用服务工件生命周期事件Cache Storage API 以及 Web 应用网络流量方面的知识,打造出精心设计的服务工件,随时处理 Web 应用的所有请求。

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

为此,请将以下代码添加到 service-worker.js,该代码会在响应各种事件时将消息记录到 DevTools 控制台(但不会执行其他操作):

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 文件中,接下来可以访问示例项目的正式版,并观察服务工件的工作情况。

  • 如需预览网站,请按 View App(查看应用)。然后按 Fullscreen(全屏)全屏
  • 按 `Control+Shift+J`(在 Mac 上为 `Command+Option+J`)打开 DevTools。
  • 点击控制台标签页。

您应该会看到类似以下日志消息的内容,表明服务工件已安装并激活:

显示 Service Worker 已安装并激活。

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

在 Service Worker 面板中显示 Service Worker 详情。

这表示,有一个源网址为 service-worker.js 的服务工作线程适用于 Web 应用 solar-donkey.glitch.me,并且目前处于启用和运行状态。它还会告知您,目前有 1 个客户端(打开的标签页)由该服务工作器控制。

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

触发 Service Worker 更新流程

使用服务工作线程进行开发时,需要了解的一个关键概念是更新流程

用户访问注册了服务工件的 Web 应用后,他们最终会获得在其本地浏览器上安装的当前 service-worker.js 副本的代码。但是,如果您更新存储在 Web 服务器上的 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);
});

进行更改后,返回示例应用的正式版,然后在 DevTools 的“Application”标签页仍处于打开状态时重新加载页面。您应该会看到如下内容:

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

这表明此时已安装两个版本的您的服务工件。已激活的旧版正在运行,并控制着当前页面。下面列出了更新后的服务工件版本。它处于 waiting 状态,并会一直等待,直到由旧服务工作线程控制的所有打开的标签页都关闭为止。

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

总结

现在,您应该已经熟悉了注册服务工作线程以及使用 Chrome 的 DevTools 观察服务工作线程行为的流程。

现在,您已经做好了开始实现缓存策略和所有其他有助于 Web 应用可靠快速加载的功能的准备。