什么是 Service Worker?
Service Worker 在实务上运用的频率不算高,但在特定的网站有支援 PWA (Progressive Web Apps) 情况下算是常见的功能。
一般来说在无网路或收讯不好的地区是无法操作网站,然而 Service Worker 支持离线操作网站,主要是 Service Worker 能 cache 住相对应资源在 client 与 server 之间担任 proxy 角色,透过下图更了解 Service Worker 在这之间的角色定位。

Servie Worker 兼容性
当今使用的浏览器版本基本上都支援 Servie Worker,除了时代的眼泪IE。
Service Worker特点
- JS Worker
以我们常使用的 Chrome 举例,当开启一个 tab 代表一个程序( Process ),而浏览器需要执行 JS 程式码必须透过JS 引擎 (V8) 将 JS 转为二进制解析并运行。
JS 运行时是单一执行绪(Thread)代表着一次只能做一件事情,而 Service Worker 创建时必须在 JS 主执行绪register,之后会在其他执行绪上面运行与 JS 执行绪不互相冲突。 - 没有
this取而代之的是self
衔接第一点,Service Worker 不是在 JS 执行绪上运行,当然在context是会有些不同。
题外话this在 JS 中常常照成开发者困扰,有时间也会再拉一个篇幅介绍this的机制。 - 没有直接访问
DOM的权限
原因与第二点相同,但有方法可以以间接的方式访问DOM这里先跳过后续会说明。 - 原则上只能在 https上运行
在前面有说到 Service Worker 是担任 client 与 server 间 proxy 的角色,为了确保网络安全所以原则上只能在https运行,但如果在开发时例外是可以在localhost或127.0.0.1上运行。
Service Worker Life Cycle

Service Worker 流程图

第一次看到上图对于刚接触 Servie Worker 来说会比较生硬,但主要可以先记住几个流程:
-
install
在触发install流程中,主要是在处理新 cache 放入 Cache Storage 中。 -
activate
在触发activate流程中,主要是在清除旧 cache 因为在install时已将新 cache 放入 Cache Storage 中。
Cache Storage 以 Chrome 举例,可以在左键 -> 检查 -> Application -> 左侧列表栏查看
补充:
install后不会直接执行activate,有以下几种方式能够触发:
1–1 关闭当前tab
1–2 等待二十四小时
1–3 手动触发
1–4 执行self.skipWaiting执行
self.skipWaiting后触发activate并不会正式启用新 Service Worker 开始代理,以下有几种方式可让新 Service Worker 接管旧 Service Worker 代理:
2–1 reload page
2–2 执行 clients.claim
Service Worker范例
前面铺垫了这么久,现在我们要创建一个 Service Worker 并实现离线快取功能,但在开始前希望大家对于 ES6 的 Promise 有一定程度上的了解,因为在 Service Worker 中会大量使用到 Promise。
这里就稍微离题介绍 Promise 学习资源:
- MDN:初识 Promise 学习资源。
- Promises/A+:在 ES6(ECMA 2015) 前 Promise 在社群中的规范以及后续 ECMA在ES6 新增 Promise 时,也有借鉴此规范并在该规范上拓展新功能。
- 手写 Promise:理解 Promise 原理及巩固 Promise 基础。
掌握第一点就能够对 Promise 有充分的理解,二三点是给想深入理解 Promise 的朋友们参考。
// 目录结构
├── index.html
├── package.json
├── src
│ └── main.js
└── sw.js
1. 注册Service Worker
// main.js