- 丰富的离线体验
- 定期的后台同步
- 推送通知
- …
以上功能通常需要原生应用程序的支持, Service Worker 提供这些功能所依赖的技术基础。
什么是 Service Worker ?
Service Worker 是浏览器在后台运行的脚本,它独立于网页。通常一个网页的打开,从输入一个 url 开始, dns 解析等等一系列操作,然后最终渲染界面,用户可以看到前端界面,但一旦处于离线状态,用户再次打开该网页就会访问失败,这种体验还是比较差的。
为了解决这类问题,我们想到的是能不能将一些静态资源等进行缓存,这样就算用户在弱网或者无网的情况下,还是能继续看到上次缓存的内容,比如博客、图片等。 Service Worker 的出现,让我们可以支持离线体验,让开发能够全面控制这一体验。
在 Service Worker 出现前,存在能够在网络上为用户提供离线体验的另一个 API,称为 AppCache),但存在许多问题,而在设计 Service Worker 时已经避免这些问题。
关于使用 Service Worker 需要注意的几点:
Service Worker是一个JavaScript Worker),无法直接访问页面的DOM。Service Worker通过响应postMessage接口发送的消息来与其控制的页面通信,页面可以在必要时对DOM进行操作;Service Worker是一个可编程网络代理,允许你控制如何处理来自页面的网络请求;Service Worker在不用时会被终止,并在下次需要时重启,因此,不能依赖Service Worker的onfetch和onmessage处理程序中的全局状态。 如果存在你需要持续保存并在重启后加以重用的信息,Service Worker可以访问IndexedDB API)。Service Worker广泛使用了promise,所以需要熟悉promise。
Service Worker 的生命周期
Service Worker 的生命周期完全独立于网页。
为网站安装 Service Worker ,需要现在页面的 JavaScript 进行注册,注册后将会通知浏览器在后台启动 Service Worker 安装步骤。
安装过程,通常需要缓存某些静态资源,当所有需要缓存的文件已成功缓存,那代表 Service Worker 安装完毕。如果存在任何文件下载失败或者缓存失败,那就会安装失败, Service Worker 无法激活,发生这种情况,它下次会再次尝试。
安装成功后,进入激活步骤,这是管理旧缓存的好方式,后续部分会介绍。激活之后, Service Worker 将会对其作用域内的所有页面进行控制,不过,首次注册该 Service Worker 的页面需要再次加载才会受其控制。当 Service Worker 对页面进行控制后,一般会处于以下两种状态之一:
Terminated,终止以节省内存;Fetch / Message,处理fetch和消息事件
以下是 Service Worker 初始化安装时的简化生命周期:

先决条件 [需要满足什么条件才能使用]
- 浏览器支持。现在基本不部分主流的浏览器已经支持使用
Service Worker,所有浏览器的支持情况可以参考该链接:https://jakearchibald.github.io/isserviceworkerready/; - 需要 使用
HTTPS,开发过程中可以通过[localhost](http://localhost)使用Service Worker,但如果需要在网站上部署Service Worker,需要在服务器上设置HTTPS。
注册 Service Worker
在安装 Service Worker 前,需要在页面中对它进行注册,然后启动安装,这一点上述步骤也提过。
1 | function registerServiceWorker() { |
通过上面代码可以分析,首先要去判断该浏览器是否支持 serviceWorker ,在页面加载后注册位于根目录 sw.js 文件,从而注册 Service Worker。每次页面加载后,都会调用 register() ,浏览器将会判断 Service Worker 是否已注册并做出相应的处理。以上代码中 sw.js 文件位于根目录,所以它的作用域将是整个来源,即 Service Worker 将接收此网站上所有事项的 fetch 事件。如果我们在 example/sw.js 处注册 Service Worker 文件,则 Service Worker 将只能看到网址以 /example/ 开头(即 /example/page1/、 /example/page2/)页面的 fetch 事件。
完成以上操作后,可以通过 chrome://inspect/#service-workers 检查 Service Worker 是否已启用。

可以通过 chrome://serviceworker-internals/ 查看所有 Service Worker 详情。
安装 Service Worker
为 install 定义回调,并缓存需要的文件。
1 | var CACHE_NAME = 'my-first-cache'; |
缓存和返回请求
1 | self.addEventListener('fetch', function (event) { |
上述代码不难理解,如果存在有缓存数据,那就直接返回数据,不需要重新 fetch 请求,否则需要走网络请求获取对应数据。在离线情况下,比如已经缓存下来的文件(如图片等)可以正常展示,那没被缓存的文件会直接请求失败,所以可以在有网情况下请求到数据后,并对数据进行相应的缓存。
1 | self.addEventListener('fetch', function (event) { |
更新 Service Worker
当 Service Worker 文件与其当前所用文件(如 sw.js)存在字节差异,则会被视为新 Service Worker 。用户进入该网站后,新的 sw.js 文件将启动,且触发 install 事件,但是旧的 sw.js 仍然会控制着当前页面,所以新的 sw.js 将进入 waiting 状态。当关闭该标签界面后,旧的 sw.js 终止,新的 sw.js 获得控制权,再次打开该界面,将会触发 activate 事件进行激活,可以查看上面的简化生命周期图。
出现在 activate 回调中的一个常见任务就是缓存管理,比如清除旧的缓存数据等,然后缓存新的数据。
1 | self.addEventListener('activate', function (event) { |
参考链接:
https://developers.google.com/web/fundamentals/primers/service-workers/
demo: