如何优雅的注销 Service Worker

有时候我们不在需要 PWA 或者其它基于 Service Worker 的功能,那应该如何优雅的注销 Service Worker 呢?

# Service Worker 如何工作

在了解如何注销 Service Worker 前,我们先大致了解下 Service Worker 如何工作

# 初次安装

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
}

在注册 Service Worker 文件后,开始将指定的一些静态资源进行离线缓存,然后 Service Worker 就会激活

# 再次访问

当再次访问时,所有的请求都会经过 Service Worker

这时候如果缓存命中,就直接返回缓存内容

如果缓存没有命中,则可以新建 fetch 请求加载相关内容

# Service Worker 更新

如果浏览器检测到 Service Worker 存在更新,就会下载新的 Service Worker 文件,执行同初次安装的缓存激活等行为

# 如何注销 Service Worker

ServiceWorkerRegistration 接口存在 unregister (opens new window) 方法,用于取消对 Service Worker 的注册。

于是可以修改原本的注册

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.getRegistrations().then((registrations) => {
    registrations.forEach(sw => sw.unregister())
  })
}

但这样不够完整,很有可能无法注销 Service Worker。

# 原因

虽然修改了注销代码,但是 Service Worker 可能没有更新。导致浏览器本地的缓存依然是旧版本,没有更新注销代码,所以可能无法注销 Service Worker。

# 解决方法

更新 Service Worker 文件,并清空缓存内容

self.addEventListener('activate', (e) => {
  e.waitUntil(
    caches.keys().then((t) => {
      return Promise.all(
        t.map((n) => {
          return caches.delete(n)
        })
      )
    })
  )
})
self.skipWaiting()

由于 Service Worker 文件存在更新,浏览器则会更新最新的 Service Worker 文件。在执行新 Service Worker 文件时,清空本地所有缓存。然后所有的请求都走服务器,所以就可以正常执行注销代码

TypeScript 推导嵌套对象类型的字符串路径

TypeScript 推导嵌套对象类型的字符串路径

TypeScript 实战,如何推导出嵌套对象类型的字符串路径

使用 createFetch 替代 Axios 在 Vue 中进行请求封装

使用 createFetch 替代 Axios 在 Vue 中进行请求封装

随着组合式函数在 Vue 中推行,是时候考虑换一种方式封装请求了