理解 Service Worker 的生命周期

2025-06-04

理解 Service Worker 的生命周期

理想的用户体验是能够不间断地访问互联网上的信息。不幸的是,即使有高速连接,我们仍然会遇到延迟。

让我简单解释一下,为了在屏幕上获取我们需要的信息,我们通过网络发送请求并等待响应。但是,如果网络繁忙,或者某个地方的代理配置错误,或者由于某种原因您无法访问互联网,那该怎么办?真的有任何事情发生,我们不得不等待很长时间?

这对于大多数用户来说可能令人沮丧。

但有一个解决方案,那就是构建Offline FirstWeb 应用程序。

但是如何实现线下体验呢?

为了实现离线体验,我们需要注意:

  1. 缓存资源。浏览器会存储一些静态资源,例如 HTML、CSS、图片等。这样,下次需要时,就可以从浏览器缓存中获取它们。网络故障时,这可就麻烦了。
  2. 在客户端存储数据。Html 5 带来了好消息,它具有 Web 存储、索引数据库等离线技术,使您可以将数据本地存储在用户设备上。
应用程序缓存

应用程序缓存(警告:已被弃用)
尝试通过允许您指定希望浏览器缓存的资源集并享受离线浏览来解决缓存问题locally,通过缓存资源提高速度(无需网络旅行),并减少服务器负载(浏览器仅从服务器下载已更改的资源。)

当用户断开网络连接时很有用,但它兑现了它的承诺吗?read API 是个混蛋

服务人员

Service Worker 是一个脚本(javascript 文件),浏览器在后台运行,充当应用程序和网络之间的代理。

服务工作者使应用程序能够拦截请求,然后修改响应,缓存这些请求以提高性能,并提供对缓存数据的离线访问,从而使其可靠。

服务工作者是一种Web 工作者,它在与网页和 UI 不同的线程上运行,使它们能够在没有活动浏览器会话的情况下工作。

它无法访问 DOM,而是通过与页面进行通信post message,然后这些页面可以在需要时操作 DOM。

它为您提供对应用程序行为的完全控制,尤其是在网络不可用或速度慢时。

这种控制是服务工作者仅在 https 上运行的原因,以避免中间人攻击,尽管本地请求是一个例外 - 在开发期间没有必要

  • 预期用途是创造线下首次体验
  • 拦截网络请求并根据网络可用性处理响应,
  • 遇到网速慢时在线上的巨大好处
  • 允许访问推送通知和后台同步

Service Worker 让你能够以不同于缓存的方式处理网络请求。Service
Worker 围绕着最近的 WebAPI 展开

  1. Fetch:当通过网络请求资源时,会触发fetch事件。执行标准请求,例如,让我们能够在发出网络请求之前查看缓存。在 Service Worker 内部,允许拦截请求,然后修改请求对象以外的内容。respondWith()用于告诉浏览器我们将处理这些请求。
  2. 缓存 API。缓存 API独立于网络状态或浏览器缓存。它允许您控制缓存的方式和时间。除非明确请求,否则它不会更新缓存中的项目。缓存中的项目不会过期,当您删除旧缓存时,它们就会消失。

服务工作者生命周期

  • 登记
  • 安装
  • 激活
登记

要使用服务工作者,您必须注册并定义其范围。

注册将告诉浏览器服务工作者的位置并开始在后台安装它。

注册服务工作者的代码放置在sw.js

    navigator.serviceWorker.register('/sw.js').then(function(){
      console.log('Registration worked!');
    }).catch(function() {
      console.log('Registration failed!');
      });
    };

Service Worker 返回一个承诺。如果 Promise 解析,则注册成功,否则新 Service Worker 的注册失败。

浏览器支持

由于某些浏览器尚不支持服务工作线程,因此请通过将服务工作线程包装在 中来执行功能检查if statement

if (!navigator.serviceWorker) return;
navigator.serviceWorker.register('/sw.js').then(function() {
    console.log('Registration worked!');
}).catch(function() {
    console.log('Registration failed!');
});
};

范围

作用域定义了 Service Worker 控制的页面。默认作用域由 Service Worker 脚本的位置定义。
这意味着,如果您在根文件夹下注册 Service Worker,则无需定义其作用域,因为它控制所有页面。

navigator.serviceworker.register('/sw.js', {
    scope: '/'
});

浏览器不会重新注册现有的服务工作者,但会返回现有注册的承诺

安装

一旦浏览器注册了 Service Worker,它就会立即downloaded认为 Service Worker 是新的,无论是通过

  1. 该 Service Worker 之前从未注册过。或者
  2. 您改变了服务工作者脚本,字节差异。

install event被解雇了。

这是一个从网络获取构成应用程序外壳的资源并缓存它们的绝佳机会。非常适合我们的网站所依赖的静态资源,例如 Html、Css、Fonts、Javascript 等。

如果之前版本的 Service Worker 已在运行,它仍将继续提供页面服务。
浏览器在安装阶段完成之前不会让新的 Service Worker 接管控制权。相反,它会成为下一个等待的版本。

为了延迟安装过程并确定其成功,我们向方法传递了一个承诺event.waitUntill

如果承诺得到解决,浏览器就知道安装已完成。如果失败,那么它将被丢弃。无需担心,因为服务工作者的先前版​​本仍在工作。

这可确保在任何给定时间仅运行一个版本的脚本。

self.addEventListener('install', function(event) {
  event.waitUntil(
     );
   }); 
激活

一旦服务工作者成功完成安装阶段,它就会进入激活阶段。

当浏览器第一次遇到 Service Worker 时,Service Worker 在成功完成安装阶段后就会变为活动状态,并且能够控制新页面的加载。但是,它无法控制已经加载的页面。要控制已经加载的页面,需要重新加载。

在 Service Worker 更新的情况下(不是浏览器第一次与 Service Worker 交互),新安装的 Service Worker 无法接管控制权,直到之前安装的 Service Worker 的所有页面都关闭为止。

一旦所有使用旧(以前安装的)服务工作线程的页面都消失,新的服务工作线程就会激活,并触发激活事件。

clients.claim()一旦激活服务工作者,您就可以通过调用服务工作者内部的函数来控制不受控制的页面

self.addEventListener('activate', function(event){
});

由于之前的版本已经不再适用,因此现在是删除旧缓存的最佳时机,以便所有用户都可以使用我们网站的当前版本。

陷阱

我们总是在修改文件!当我们修改文件(比如 CSS 文件)时,这可能会成为一个“问题”。页面重新加载也无济于事,因为我们仍然在使用旧 CSS 的缓存。

尽管我们的 css 文件发生了变化,但我们的网站仍然保持不变。这意味着,要查看更改,我们需要对服务工作脚本进行更改,您只需添加一条注释,记住它只是一个字节差异,浏览器会将其视为“新的”

笔记

  1. Service Worker 不仅提供离线使用的缓存数据,而且在在线连接速度较慢时也能有效使用。
  2. Service Worker 是可编程的 JavaScript“仆人/工作者”
  3. 它们不能直接访问 DOM,而是通过响应消息来与其控制的页面进行通信postmessage
  4. 要求网站通过 https 提供服务。这一点很重要,因为它们会拦截请求并修改响应,以避免被第三方劫持。
  5. 不使用时保持空闲状态,下次需要时重新启动
  6. 充分利用承诺

进一步阅读:

  1. 服务作品简介

  2. 杰克·阿奇博尔德

结论

感谢您的阅读,希望您准备好为用户提供线上和线下的精彩体验。如果您喜欢这篇文章或者我错过了什么,请告诉我!

在 Twitter 上与我联系

文章来源:https://dev.to/achiengcindy/understanding-the-service-worker-lifecycle-47d5
PREV
面向 Web 开发人员的 6 大免费工具
NEXT
理解 NodeJS 集群模块(1/4)