Service Worker API

Service worker 本质上充当 Web 应用程序、浏览器与网络(可用时)之间的代理服务器。这个 API 旨在创建有效的离线体验,它会拦截网络请求并根据网络是否可用来采取适当的动作、更新来自服务器的资源。它还提供入口以推送通知和访问后台同步 API。

Service worker 的概念和用法

Service worker 是一个注册在指定源和路径下的事件驱动 worker。它采用 JavaScript 文件的形式,控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。你可以完全控制应用在特定情形(最常见的情形是网络不可用)下的表现。

Service worker 运行在 worker 上下文:因此它无法访问 DOM,相对于驱动应用的主 JavaScript 线程,它运行在其他线程中,所以不会造成阻塞。它被设计为完全异步;因此,同步 XHRWeb Storage 不能在 service worker 中使用。

出于安全考量,Service worker 只能由 HTTPS 承载,毕竟修改网络请求的能力暴露给中间人攻击会非常危险,如果允许访问这些强大的 API,此类攻击将会变得很严重。在 Firefox 浏览器的用户隐私模式,Service Worker 不可用。

备注: 在 Firefox,为了进行测试,你可以通过 HTTP 运行 service worker(不安全);只需选中 Firefox 开发者选项/齿轮菜单中的 Enable Service Workers over HTTP (when toolbox is open) 选项。

备注: 与之前在该领域的尝试不同,如 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 已启用,新版本会在后台安装,但仍不会被激活——这个时序称为 worker in waiting。直到所有已加载的页面不再使用旧的 service worker 才会激活新的 service worker。只要页面不再依赖旧的 service worker,新的 service worker 会被激活(成为 active worker)。使用 ServiceWorkerGlobalScope.skipWaiting() 可以更快地进行激活,active worker 可以使用 Clients.claim() 声明现有的页面

你可以监听 install (en-US) 事件;该事件触发时的标准行为是准备 service worker 用于使用,例如使用内建的 storage API 来创建缓存,并且放置应用离线时所需资源。

还有一个 activate (en-US) 事件。此事件触发的时间点通常是清理旧缓存以及其他与你的 service worker 的先前版本相关的东西的好时机。

Servcie worker 可以通过 FetchEvent 事件去响应请求。通过使用 FetchEvent.respondWith 方法,你可以任意修改对于这些请求的响应。

备注: 因为 oninstallonactivate 完成前需要一些时间,service worker 标准提供一个 waitUntil() 方法。一旦在带有 promise 的 installactivate 事件上调用它,那么 fetchpush 等功能事件将等待,直到 promise 成功兑现。

构建一个基本用例的完整教程,请阅读使用 Service Worker

其他使用场景

Service workers 也可以用来做这些事情:

  • 后台数据同步
  • 响应来自其他源的资源请求
  • 集中接收计算成本高的数据更新,比如地理位置和陀螺仪信息,这样多个页面就可以利用同一组数据
  • 在客户端进行 CoffeeScript、LESS、CJS/AMD 等模块编译和依赖管理(用于开发目的)
  • 后台服务钩子
  • 自定义模板用于特定 URL 模式
  • 性能增强,比如预取用户可能需要的资源,比如相册中的后面数张图片

未来 service worker 能够用来做更多使 web 平台接近原生应用的事。值得关注的是,其他标准也能并且将会使用 service worker,例如:

  • 后台同步:启动一个 service worker 即使没有用户访问特定站点,也可以更新缓存
  • 响应推送:启动一个 service worker 向用户发送一条信息通知新的内容可用
  • 对时间或日期作出响应
  • 进入地理围栏

接口

Cache

表示用于 Request / Response 对象对的存储,作为 ServiceWorker 生命周期的一部分被缓存。

CacheStorage

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

Client

表示 service worker client 的作用域。一个 service worker client 可以是浏览器上下文的一个文档,也可以是一个由 active worker 控制的 SharedWorker

Clients

表示一个 Client 对象容器;是访问当前源的活动的 service worker client 的主要途径。

ExtendableEvent

扩展被分发到 ServiceWorkerGlobalScopeinstallactivate 事件时序,作为 service worker 生命周期的一部分。这会确保任何功能型事件(如 FetchEvent)不被分发到 ServiceWorker,直到它更新了数据库架构、删除过期缓存项等等以后。

ExtendableMessageEvent (en-US)

向 service worker 触发的 message (en-US) 事件的时间对象(当 ServiceWorkerGlobalScope 从另一个上下文收到通道消息),延长了此类事件的生命周期。

FetchEvent

传递给 ServiceWorkerGlobalScope.onfetch 处理函数的参数,FetchEvent 代表一个在 ServiceWorkerServiceWorkerGlobalScope 中分发的请求动作。它包含关于请求和响应的结果信息,并且提供 FetchEvent.respondWith() 方法,这个方法允许我们提供任意的响应返回到控制页面。

InstallEvent 已弃用 非标准

传递给 oninstall 处理函数的参数,InstallEvent 接口代表一个在 ServiceWorkerServiceWorkerGlobalScope 中分发的安装动作,作为 ExtendableEvent 的子事件,它保证诸如 FetchEvent 的功能性事件在安装过程中不会被分发。

提供与 service worker 一起管理资源预加载的方法。

返回一个 ServiceWorkerContainer 对象,该对象提供对相关 document 的注册、删除、更新以及与 ServiceWorker 对象通信的访问。

NotificationEvent

传递给 onnotificationclick 处理函数的参数,NotificationEvent 接口代表在 ServiceWorkerServiceWorkerGlobalScope 中分发的单击事件通知。

ServiceWorker

表示一个 service worker。多个浏览的上下文 (例如 page、worker 等等) 都能通过相同的 ServiceWorker 对象相关联。

ServiceWorkerContainer

提供一个在网络生态中把 service worker 作为一个整体的对象,包括辅助注册,反注册以及更新 service worker,并且访问 service worker 的状态以及他们的注册信息。

ServiceWorkerGlobalScope

表示 service worker 的全局执行上下文。

MessageEvent

表示发送到 ServiceWorkerGlobalScope 的信息。

ServiceWorkerRegistration (en-US)

表示 service worker 的注册。

SyncEvent (en-US) 非标准

SyncEvent 接口代表在 ServiceWorker 的 ServiceWorkerGlobalScope 上分发的同步动作。

SyncManager (en-US) 非标准

提供用于注册和列出同步注册的接口。

WindowClient (en-US)

表示在浏览器上下文中记录的 service worker 客户端的作用域,被活动的工作者控制。是 Client 对象的特殊类型,包含一些附加的方法和可用的属性。

规范

Specification
Service Workers

参见