跳到主要内容

认识

2025年01月19日
柏拉文
越努力,越幸运

一、认识


Service Worker 是一种运行在浏览器后台的脚本,位于应用程序和网络之间的中间层,允许开发者拦截和处理网络请求,从而实现离线支持、资源缓存、推送通知等功能。它是 PWAProgressive Web Apps)的核心技术之一。

Service worker 本质上充当 Web 应用程序、浏览器与网络(可用时)之间的代理服务器。这个 API 旨在创建有效的离线体验,它会拦截网络请求并根据网络是否可用来采取适当的动作、更新来自服务器的资源。它还提供入口以推送通知和访问后台同步 APIService Worker 在浏览器后台运行,与主线程隔离,因此不会阻塞页面渲染。可以通过事件监听(如 fetch)来拦截并处理网页的网络请求。通过 Cache API,可以缓存静态资源,实现离线访问和快速加载。Service Worker 有明确的安装(install)、激活(activate)、运行(fetch)等生命周期。必须在 HTTPS 环境下运行(或者在 localhost 开发环境中允许非 HTTPS)。Service Worker 运行在独立的线程中,无法直接操作 DOM

Service Worker 工作流:

1. 注册 Service Worker: Service Worker 使用 ServiceWorkerContainer.register() 方法首次注册 service worker。如果注册成功,用户首次访问 service worker 控制的网站或页面时,service worker 会立刻被下载。service worker 将在 ServiceWorkerGlobalScope 中执行;这本质上是一种特殊的上下文,在主脚本执行线程之外运行,没有访问 DOM 的权限。Service Worker 现在已为处理事件做好准备。

2. 安装(install: 在浏览器下载并解析完 Service Worker 文件后触发。通常用于缓存静态资源。当下载的文件发现是最新的时,就会试图安装——要么与现有的 service worker 不同(字节对比),要么是在页面或网站遇到的第一个 service worker。如果这是首次启用 service worker,页面会首先尝试安装,安装成功后它会被激活。install 事件始终是发送给 service worker 的第一个事件(这可用于启动填充 IndexedDB 和缓存站点资源的过程)。在此步骤期间,应用程序正在为离线可用做准备。

3. 激活(activate: 新的 Service Worker 替换旧的后触发。常用于清理旧的缓存或初始化资源。如果现有 service worker 已启用,新版本会在后台安装,但仍不会被激活——这个时序称为 worker in waiting。直到所有已加载的页面不再使用旧的 service worker 才会激活新的 service worker。只要页面不再依赖旧的 service worker,新的 service worker 会被激活(成为 active worker)。一旦 service worker 的旧版本控制的页面都已关闭,就可以安全地停用旧版本,并且新安装的 service worker 将收到 activate 事件。activate 的主要用途是去清理 service worker 之前版本使用的资源。新的 service worker 可以调用 skipWaiting() 要求立即激活,而无需要求打开的页面关闭。然后,新的 service worker 将立即收到 activate 事件,并将接管任何打开的页面。激活后,service worker 将立即控制页面,但是只会控制那些在 register() 成功后打开的页面。换句话说,文档必须重新加载才能真正的受到控制,因为文档在有或者没有 service worker 的情况下开始存在,并在其生命周期内维护它。为了覆盖次默认行为并在页面打开的情况下,service worker 可以调用 clients.claim() 方法。每当获取新版本的 service worker 时,都会再次发生此循环,并在新版本的激活期间清理上一个版本的残留。

4. 运行(fetchpush: 激活后的 Service Worker 监听 fetch 等事件,控制网络请求。

5. 更新(update: 浏览器检测到 Service Worker 文件发生变化时,下载新文件并安装。一个前往作用域内页面的导航或者在 service worker 上的一个事件被触发并且过去 24 小时没有被下载时会触发更新

Service Worker 可用事件:

  • install: 通过 ServiceWorkerContainer.register() 注册完成, 用户首次访问 service worker 控制的网站或页面时,service worker 会立刻被下载。 在浏览器下载并解析完 Service Worker 文件后触发 install 事件。install 事件通常会这样用,将离线运行 app 产生的资源放置在浏览器离线缓存的空间。

  • activate: 新的 Service Worker 替换旧的后触发。

  • message

  • fetch

  • sync

  • push

二、语法


2.1 创建 Service Worker

service-worker.js 文件

self.addEventListener("install", (event) => {
console.log('Service Worker 安装中...');
});

self.addEventListener('activate', event => {
console.log('Service Worker 激活');
});

self.addEventListener('fetch', event => {
console.log('拦截请求:', event.request.url);
});

2.2 主线程注册 Service Worker

使用 ServiceWorkerContainer.register() 方法首次注册 service worker

const registerServiceWorker = async () => {
if ("serviceWorker" in navigator) {
try {
const registration = await navigator.serviceWorker.register("/sw.js", {
scope: "/",
});
if (registration.installing) {
console.log("正在安装 Service worker");
} else if (registration.waiting) {
console.log("已安装 Service worker installed");
} else if (registration.active) {
console.log("激活 Service worker");
}
} catch (error) {
console.error(`注册失败:${error}`);
}
}
};

registerServiceWorker();