Service Worker 生命周期
https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle?hl=zh-cn
第一个 Service Worker
install 事件是 SW 触发的第一个事件,并且仅触发一次。
installEvent.waitUntil() 接收一个 Promise 参数,用它来表示 SW 安装的成功与否。
SW 在安装成功并激活之前,不会响应 fetch 或 push 等事件。
默认情况下,页面的请求(fetch)不会通过 SW,除非它本身是通过 SW 获取的,也就是说,在安装 SW 之后,需要刷新页面才能有效果。clients.claim() 可以改变这种默认行为。
install 是在 SW 控制 clients 之前处理缓存很好的时机。
安装成功后并激活(activate)成功后,SW 就可以处理"功能性的事件"了,比如push,sync。但这并不代表调用 .register() 的页面会立即生效,你可以在 activate 事件中通过调用 clients.claim() 来让没被控制的 clients 受控。
在同域的任何 URI 上添加 clear-site-data "storage" 响应头 unregister sw // 下次生效
更新 Service Worker
- 触发更新的几种情况:
- 第一次导航到作用域范围内页面的时候
- 更新 push 和 sync 等功能事件,除非在前 24 小时内进行了更新检查。
- SW 的 URL 发生变化并调用.register()时
- 当 SW 代码发生变化,SW 会做更新(还将包括引入的脚本)
- 更新后的 SW 会和原始的 SW 共同存在,并运行它的install
- 如果新的 SW 不是成功状态,比如 404,解析失败,执行中报错或者在 install 过程中被 reject,它将会被废弃,之前版本的 SW 还是激活状态不变。
- 一旦新 SW 安装成功,它会进入wait状态直到原始 SW 不控制任何 clients。
- self.skipWaiting() 可以阻止等待,让新 SW 安装成功后立即激活。
触发更新算法后,浏览器会检查并遵循 sw.js 的文件缓存(HTTP 缓存)设置,比如 max-age。 这意味着:
- 如果不设置 sw.js 的 HTTP 缓存,每次页面加载该文件都会被请求。
- 如果设置了 10s 的缓存,则 10s 内浏览器不会再次访问服务器。
- // 更新 sw 自身肯定不会通过 sw
"尽管这个例子中你仅打开了一个 tab,但刷新页面并没有用,这是由于浏览器本身的机制,当你刷新的时候,当前页面不会离开,直到收到了一个响应头,而且即使这样,如果响应中包含Content-Disposition的话,当前页面还是不会离开。由于这个时间上的重叠,在刷新的时候当前的 SW 总是控制了一个 client。"
Activate 在旧的 SW 离开时会被触发,在event.waitUntil()中传入了一个 Promise,SW 将会缓存住功能性事件(fetch,push,sync等等),直到 Promise 返回 resolve 的时候再触发,也就是说,当你的fetch事件被触发的时候,SW 已经被完全激活了。
如果你强制刷新页面,那么会绕过 SW,变成不受控,这个功能已被定为规范,所以在其他支持 SW 的浏览器中也适用。
Cache API 跟 HTTP 缓存控制互不相干, 更新 sw 是不能通过 sw 本身来代理的
service worker 中的事件 sync push 等都能在被 kill 掉之后触发。
更新完 sw 后 Client 会触发 controllerchange 事件
给用户提示进行更新:
- 浏览器检测到存在新的(不同的)SW 时,安装并让它等待,同时触发 updatefound 事件
- 我们监听事件,弹出一个提示条,询问用户是不是要更新 SW
- 如果用户确认,则向处在等待的 SW 发送消息,要求其执行 skipWaiting 并取得控制权
- 因为 SW 的变化触发 controllerchange 事件,我们在这个事件的回调中刷新页面即可