Service Worker API

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

Service Worker 本质上充当着 Web 应用程序、浏览器和网络(在可用时)之间的代理服务器。它们旨在实现包括但不限于:创建有效的离线体验、拦截网络请求,并根据网络是否可用采取相应措施、更新服务器上的资源。它们还将允许访问推送通知和后台同步 API。

注意: Service Worker 是一种 Web Worker。有关 Worker 类型和用例的通用信息,请参阅 Web Workers

Service Worker 概念与用法

Service Worker 是一个事件驱动的 Worker,它针对特定的源(origin)和路径进行注册。它采用 JavaScript 文件的形式,可以控制与之关联的网页/站点,拦截和修改导航和资源请求,并以非常精细的方式缓存资源,从而让您完全掌控应用程序在某些情况下的行为(最明显的就是网络不可用时)。

Service Worker 在 Worker 上下文中运行:因此,它们没有 DOM 访问权限,并且与驱动您应用程序的主 JavaScript 运行在不同的线程上。它们是非阻塞的,并且被设计为完全异步的。因此,像同步 XHRWeb Storage 这样的 API 不能在 Service Worker 中使用。

Service Worker 不能动态导入 JavaScript 模块,如果在 Service Worker 的全局作用域中调用 import(),将会抛出错误。使用 import 语句的静态导入是允许的。

Service Worker 仅在 安全上下文 中可用:这意味着它们的文档是通过 HTTPS 提供的,尽管浏览器也将 https:// 视为安全上下文,以方便本地开发。HTTP 连接容易受到 中间人 攻击的恶意代码注入,并且允许访问这些强大 API 的攻击可能会造成更严重的后果。

注意: 在 Firefox 中,为了测试,您可以允许 Service Worker 在 HTTP(不安全)下运行;只需在 Firefox 开发者工具的选项/齿轮菜单中勾选 **在工具箱打开时,允许 Service Workers 在 HTTP 上运行** 选项。

注意: 与该领域之前的尝试(例如 AppCache)不同,Service Worker 不会假设您试图做什么,然后在这些假设不完全正确时崩溃。相反,Service Worker 为您提供了更精细化的控制。

注意: Service Worker 大量使用 Promise,因为通常它们会等待响应通过,然后它们将以成功或失败的操作进行响应。Promise 架构非常适合这一点。

注册

Service Worker 首先使用 ServiceWorkerContainer.register() 方法进行注册。如果成功,您的 Service Worker 将被下载到客户端,并尝试为用户在其源(origin)内的所有 URL 或您指定的子集进行安装/激活(见下文)。

下载、安装和激活

此时,您的 Service Worker 将遵循以下生命周期:

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

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

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

  • 导航到作用域内的页面时。
  • Service Worker 触发了一个事件,并且在过去 24 小时内没有下载它。

当找到新文件(与现有 Service Worker 字节比较不同,或者这是此页面/站点遇到的第一个 Service Worker)时,会尝试安装。

如果这是第一次提供 Service Worker,则会尝试安装,然后在成功安装后,激活它。

如果已有 Service Worker,则新版本会在后台安装,但尚未激活——此时它被称为“待定 Worker”(worker in waiting)。只有当不再有使用旧 Service Worker 的页面加载时,它才会激活。一旦没有更多页面需要加载,新的 Service Worker 就会激活(成为“活动 Worker”,active worker)。激活可以更早地使用 ServiceWorkerGlobalScope.skipWaiting() 完成,并且现有页面可以使用 Clients.claim() 被活动 Worker 认领。

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

还有一个 activate 事件。此事件触发的时间通常是清理旧缓存和其他与 Service Worker 上一版本相关的对象的好时机。

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

注意: 由于 install/activate 事件可能需要一段时间才能完成,Service Worker 规范提供了一个 waitUntil() 方法。一旦在 installactivate 事件上使用 Promise 调用了它,像 fetchpush 这样的功能事件将一直等到 Promise 成功解析。

有关构建第一个基本示例的完整教程,请阅读 使用 Service Workers

使用静态路由控制资源获取方式

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 来向用户发送消息,告知他们有新内容可用。
  • 响应特定时间和日期。
  • 进入地理围栏。

接口

Cache

代表在 Service Worker 生命周期中缓存的 Request / Response 对象对的存储。

CacheStorage

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

Client

代表 Service Worker 客户端的作用域。Service Worker 客户端可以是浏览器上下文中的一个文档,也可以是受活动 Worker 控制的 SharedWorker

Clients

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

ExtendableEvent

在 Service Worker 生命周期中,扩展了分派到 ServiceWorkerGlobalScopeinstallactivate 事件的生命周期。这确保了像 FetchEvent 这样的功能性事件在 Service Worker 升级数据库模式、删除过时缓存条目等操作完成之前不会被分派。

ExtendableMessageEvent

当消息通道在 ServiceWorkerGlobalScope 与其他上下文之间接收时,分派到 Service Worker 的 message 事件的对象——扩展了这些事件的生命周期。

FetchEvent

传递给 onfetch 处理程序的参数,FetchEvent 代表分派到 Service Worker 的 ServiceWorkerGlobalScope 的一个 fetch 操作。它包含有关请求和响应的信息,并提供了 FetchEvent.respondWith() 方法,该方法允许我们将任意响应提供给受控制的页面。

InstallEvent

传递给 install 事件处理函数参数的 InstallEvent 接口代表一个分派到 Service Worker 的 ServiceWorkerGlobalScope 的 install 操作。作为 ExtendableEvent 的子类,它确保在安装期间不会分派像 FetchEvent 这样的功能性事件。

提供了管理 Service Worker 资源预加载的方法。

ServiceWorker

代表一个 Service Worker。多个浏览上下文(例如,页面、Worker 等)可以与同一个 ServiceWorker 对象关联。

ServiceWorkerContainer

提供了一个代表 Service Worker 作为网络生态系统中整体单元的对象,包括注册、注销和更新 Service Worker 的功能,以及访问 Service Worker 及其注册的状态。

ServiceWorkerGlobalScope

代表 Service Worker 的全局执行上下文。

ServiceWorkerRegistration

代表一个 Service Worker 注册。

WindowClient

代表一个 Service Worker 客户端的作用域,该客户端是浏览器上下文中的一个文档,由活动 Worker 控制。这是 Client 对象的一种特殊类型,具有一些额外的可用方法和属性。

其他接口的扩展

Window.cachesWorkerGlobalScope.caches

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

返回一个 ServiceWorkerContainer 对象,该对象提供访问与关联文档ServiceWorker 对象的注册、删除、升级和通信。

规范

规范
Service Workers

另见