Service Worker API

注意:此功能在 Web Worker 中可用。

Service Worker 本质上充当 Web 应用、浏览器和网络(如果可用)之间的代理服务器。它们旨在(除其他事项外)实现有效的离线体验、拦截网络请求并根据网络是否可用采取适当的操作,以及更新服务器上的资源。它们还将允许访问推送通知和后台同步 API。

Service Worker 的概念和使用

Service Worker 是一个事件驱动的 Worker,注册到一个来源和路径。它采用 JavaScript 文件的形式,可以控制与其关联的网页/网站,拦截和修改导航和资源请求,并以非常细粒度的形式缓存资源,以便您完全控制应用程序在某些情况下(最明显的是当网络不可用时)的行为。

Service Worker 在工作程序上下文中运行:因此它们没有 DOM 访问权限,并且在与为您的应用程序提供动力的主 JavaScript 不同的线程上运行。它们是非阻塞的,旨在完全异步。因此,诸如同步 XHRWeb 存储 之类的 API 无法在 Service Worker 内部使用。

Service Worker 无法动态导入 JavaScript 模块,并且 import() 如果在 Service Worker 全局范围内调用,将抛出异常。使用 import 语句的静态导入是允许的。

出于安全原因,Service Worker 只能通过 HTTPS 运行。最重要的是,HTTP 连接容易受到 中间人 攻击的恶意代码注入,如果允许访问这些强大的 API,此类攻击可能会更糟。在 Firefox 中,Service Worker API 也会被隐藏,并且在用户处于 隐私浏览模式 下时无法使用。

注意:在 Firefox 中,为了进行测试,您可以通过 HTTP(不安全)运行 Service Worker;只需在 Firefox Devtools 的选项/齿轮菜单中选中“启用 HTTP 上的 Service Worker(当工具箱打开时)”选项即可。

注意:与该领域中以前的尝试(如 AppCache)不同,Service Worker 不会对您要执行的操作进行假设,然后在这些假设不完全正确时中断。相反,Service Worker 为您提供了更加细粒度的控制。

注意:Service Worker 大量使用 Promise,因为它们通常会等待响应到来,然后才会以成功或失败操作进行响应。Promise 架构非常适合这种情况。

注册

首先使用 ServiceWorkerContainer.register() 方法注册 Service Worker。如果成功,您的 Service Worker 将被下载到客户端,并尝试为用户在整个来源或您指定的子集中访问的 URL 安装/激活(见下文)。

下载、安装和激活

此时,您的 Service Worker 将观察以下生命周期

  1. 下载
  2. 安装
  3. 激活

当用户首次访问受 Service Worker 控制的网站/页面时,Service Worker 会立即被下载。

在那之后,它会在以下情况下更新

  • 导航到范围内页面。
  • 在 Service Worker 上触发事件,并且它在过去 24 小时内没有被下载。

如果发现下载的文件是新的,则尝试安装 — 与现有 Service Worker 不同(逐字节比较),或者针对此页面/网站遇到的第一个 Service Worker。

如果这是第一次使用 Service Worker,则尝试安装,然后在安装成功后激活。

如果存在可用的现有 Service Worker,则新版本将在后台安装,但尚未激活 — 此时它被称为等待中的工作程序。只有当不再加载使用旧 Service Worker 的页面时,它才会被激活。一旦不再加载任何页面,新 Service Worker 就会激活(成为活动工作程序)。可以使用 ServiceWorkerGlobalScope.skipWaiting() 更早地进行激活,而活动工作程序可以使用 Clients.claim() 声明现有页面。

您可以监听 install 事件;当此事件触发时,一个标准操作是为使用您的 Service Worker 做好准备,例如使用内置存储 API 创建一个缓存,并将您希望用于离线运行应用程序的资源放在其中。

还有一个 activate 事件。此事件触发的点通常是清理旧缓存和与您的 Service Worker 的先前版本相关的其他内容的好时机。

您的 Service Worker 可以使用 FetchEvent 事件响应请求。您可以使用 FetchEvent.respondWith() 方法以任何您想要的方式修改对这些请求的响应。

注意:因为 install/activate 事件可能需要一段时间才能完成,所以 Service Worker 规范提供了 waitUntil() 方法。一旦它在 installactivate 事件上使用 Promise 被调用,功能性事件(如 fetchpush)将等待 Promise 成功解析。

要了解如何构建第一个基本示例的完整教程,请阅读 使用 Service Worker

使用静态路由控制如何获取资源

Service Worker 会产生不必要的性能成本 — 当页面在一段时间后首次加载时,浏览器必须等待 Service Worker 启动并运行才能知道要加载哪些内容以及它是否应该从缓存或网络获取。

如果您已经提前知道某些内容应该从哪里获取,您可以完全绕过 Service Worker 并立即获取资源。可以使用 InstallEvent.addRoutes() 方法来实现此用例等等。

其他用例想法

Service Worker 还旨在用于诸如以下方面

  • 后台数据同步。
  • 响应来自其他来源的资源请求。
  • 接收对难以计算的数据(如地理位置或陀螺仪)的集中更新,以便多个页面可以使用一组数据。
  • 用于开发目的的 CoffeeScript、less、CJS/AMD 模块等的客户端编译和依赖管理。
  • 后台服务的钩子。
  • 基于特定 URL 模式的自定义模板化。
  • 性能增强,例如预取用户可能很快需要的资源,例如相册中的接下来的几张图片。
  • API 模拟。

将来,Service Worker 将能够为 Web 平台执行许多其他有用的操作,这将使其更接近原生应用程序的可行性。有趣的是,其他规范可以并且将开始使用 Service Worker 上下文,例如

  • 后台同步:即使没有用户在网站上,也可以启动 Service Worker,以便更新缓存等等。
  • 对推送消息做出反应:启动 Service Worker 向用户发送消息,告知他们有新内容可用。
  • 对特定时间和日期做出反应。
  • 进入地理围栏。

接口

缓存

表示 Request / Response 对象对的存储,这些对象对作为 ServiceWorker 生命周期的一部分进行缓存。

CacheStorage

表示 Cache 对象的存储。它提供了 ServiceWorker 可以访问的所有命名缓存的主目录,并维护字符串名称到相应 Cache 对象的映射。

客户端

表示 Service Worker 客户端的范围。Service Worker 客户端可以是浏览器上下文中的文档,也可以是 SharedWorker,由活动工作程序控制。

客户端

表示 Client 对象列表的容器;访问当前来源的活动 Service Worker 客户端的主要方式。

ExtendableEvent

扩展了在 ServiceWorkerGlobalScope 上分派的 installactivate 事件的生命周期,作为 Service Worker 生命周期的一部分。这确保任何功能性事件(如 FetchEvent)都不会分派到 ServiceWorker,直到它升级数据库架构并删除过时的缓存条目等等。

ExtendableMessageEvent

在 Service Worker 上触发的 message 事件(当从另一个上下文在 ServiceWorkerGlobalScope 上接收到通道消息时)的事件对象 — 扩展了此类事件的生命周期。

FetchEvent

传递到 onfetch 处理程序的参数 FetchEvent 表示在 ServiceWorkerGlobalScopeServiceWorker 上分派的提取操作。 它包含有关请求和结果响应的信息,并提供 FetchEvent.respondWith() 方法,该方法允许我们向受控页面提供任意响应。

InstallEvent

传递到 install 事件处理程序函数的参数,InstallEvent 接口表示在 ServiceWorkerGlobalScopeServiceWorker 上分派的安装操作。 作为 ExtendableEvent 的子类,它确保在安装期间不会分派诸如 FetchEvent 之类的功能事件。

提供用于管理使用服务工作者预加载资源的方法。

ServiceWorker

表示一个服务工作者。 多个浏览上下文(例如页面、工作者等)可以与同一个 ServiceWorker 对象关联。

ServiceWorkerContainer

提供一个对象,该对象表示服务工作者作为网络生态系统中的整体单元,包括用于注册、注销和更新服务工作者的工具,以及访问服务工作者及其注册的状态。

ServiceWorkerGlobalScope

表示服务工作者的全局执行上下文。

ServiceWorkerRegistration

表示一个服务工作者注册。

WindowClient

表示服务工作者客户端的范围,该客户端是浏览器上下文中的一个文档,受活动工作者控制。 这是一个特殊的 Client 对象类型,它提供了一些额外的可用方法和属性。

对其他接口的扩展

Window.cachesWorkerGlobalScope.caches

返回与当前上下文关联的 CacheStorage 对象。

返回一个 ServiceWorkerContainer 对象,该对象提供对注册、删除、升级以及与 ServiceWorker 对象进行通信的访问权限,以供 关联文档 使用。

规范

规范
服务工作者

另请参阅