前端缓存 Service workers 详解

Service Worker 是什么

Service Worker 是一个在浏览器中运行的 JavaScript 脚本,它为Web应用程序提供了一种在后台执行的机制。它的主要用途是处理离线缓存、推送通知、网络请求拦截和消息传递等功能,这些功能可以改善Web应用程序的性能和用户体验。

Service Worker运行在一个独立的线程中,因此它不会阻塞主页面的渲染和用户交互,从而改善了性能。然而,由于它的强大功能和潜在的安全风险,使用Service Worker需要小心谨慎,确保安全性和合理性。

Service Worker 主要特点和用途是什么那

  1. 离线缓存:Service Worker可以将网站资源(如HTML、CSS、JavaScript、图像等)缓存到本地,使网站能够在离线状态下继续运行。这提供了更好的离线体验,尤其在移动设备上或网络不稳定的环境中。

  2. 网络请求拦截:Service Worker可以拦截网页发出的网络请求,从缓存中获取资源,或者将请求代理到服务器。这允许开发人员实施自定义的缓存策略,以提高性能和效率。

  3. 推送通知:Service Worker允许网站发送推送通知,即使网站并未打开在浏览器中。这对于实时通知用户非常有用,例如新消息、提醒或更新。

  4. 后台同步:Service Worker可以在后台执行任务,例如数据同步或更新,而无需打开网站。这对于定期更新数据或执行其他自动化任务很有用。

  5. 消息传递:Service Worker可以与页面之间以及与服务器进行双向通信,这为构建高度交互性的Web应用程序提供了便利。

Service Worker 生命周期是什么

  • 注册 :首次访问页面时,浏览器会尝试注册一个 Service Worker 脚本。你通常在页面中使用 JavaScript 的 navigator.serviceWorker.register() 方法来进行注册。
  • 安装 :当 Service Worker 脚本成功注册时,它会执行 install 事件处理程序。在这个事件处理程序中,你可以缓存网站的静态资源,以便在以后离线使用。通常,这个阶段用于初始化 Service Worker。
  • 激活:一旦 Service Worker 安装成功,浏览器会尝试激活新的 Service Worker。在激活阶段,你可以执行清理旧缓存、删除不再需要的资源等操作。Service Worker 只有在成功激活后才能控制客户端的网络请求。
  • 控制客户端:一旦 Service Worker 被激活,它可以控制与之关联的客户端,包括网页或其他客户端。在这个阶段,Service Worker 可以拦截网络请求、处理推送通知、接收消息等。它会持续运行,直到被注销或停止。
  • 更新:当你更新 Service Worker 脚本时,浏览器会检测到新版本,并将其下载。新版本的 Service Worker 会经历安装、激活和控制客户端的阶段,以确保平稳的过渡。通常,你可以在新版本的 Service Worker 中更新缓存或执行其他操作,以提供更好的用户体验
  • 注销 :Service Worker 可以被手动注销,或者在脚本中调用 self.skipWaiting() 方法来强制激活新版本。这可以用于确保新的 Service Worker 能够立即控制客户端,而不需要等待旧版本自然过期。

Service Worker 用法

Service Worker 如何注册

注册 Service Worker:使用 navigator.serviceWorker.register() 方法注册 Service Worker。通常,这会在页面加载时或在合适的时机执行。

javascript 复制代码
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js')
    .then((registration) => {
      console.log('Service Worker registered with scope:', registration.scope);
    })
    .catch((error) => {
      console.error('Service Worker registration failed:', error);
    });
}

在上述代码中,navigator.serviceWorker.register('/service-worker.js') 会尝试注册位于根目录下的 service-worker.js 文件作为 Service Worker。

处理注册成功和失败:register() 方法返回一个 Promise,可以使用 .then() 处理注册成功的情况,以及使用 .catch() 处理注册失败的情况。在注册成功后,你可以获得一个包含有关 Service Worker 注册的信息的对象,如上述代码所示。

请注意,Service Worker 必须位于与网页相同的域中,以便进行注册。否则,由于安全策略的限制,Service Worker 无法注册成功。

一旦 Service Worker 注册成功,它将开始安装并激活,然后可以开始控制与之关联的客户端(例如网页),执行缓存、网络请求拦截、推送通知等任务。

Service Worker 如何控制客户端

  1. 拦截和处理网络请求:Service Worker 可以通过拦截客户端发出的网络请求来控制它们。你可以检查请求,从缓存中获取响应,或者将请求代理到服务器。这使你能够实现离线支持、缓存策略、网络请求重试等功能。

例如,下面是一个拦截并从缓存中获取资源的示例:

csharp 复制代码
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      return response || fetch(event.request);
    })
  );
});
  1. 向客户端发送消息 :Service Worker 可以通过使用 postMessage 方法向客户端发送消息。客户端可以监听 message 事件以接收并响应消息。 在 Service Worker 中发送消息:
javascript 复制代码
self.clients.matchAll().then((clients) => {
  clients.forEach((client) => {
    client.postMessage('Hello from Service Worker!');
  });
});

在客户端中监听消息:

javascript 复制代码
navigator.serviceWorker.addEventListener('message', (event) => {
  console.log('Message from Service Worker:', event.data);
});
  1. 推送通知:Service Worker 可以用于处理推送通知,从服务器发送通知到客户端。一旦推送通知到达,Service Worker 可以展示通知或执行其他操作,以提醒用户或执行相关任务。
csharp 复制代码
self.addEventListener('push', (event) => {
  const options = {
    body: event.data.text(),
    icon: '/icon.png',
  };

  event.waitUntil(
    self.registration.showNotification('Push Notification', options)
  );
});
  1. 同步任务:Service Worker 还支持后台同步,这意味着它可以在客户端离线时执行任务,然后在网络连接可用时同步数据。

例如,你可以使用后台同步来上传离线时保存的数据到服务器:

csharp 复制代码
self.addEventListener('sync', (event) => {
  if (event.tag === 'sync-task') {
    // 执行同步任务
    event.waitUntil(doSyncTask());
  }
});

Service Worker 如何注销

要注销(解除注册)一个 Service Worker,你可以使用 navigator.serviceWorker.getRegistration()unregister() 方法。这允许你手动取消注册一个 Service Worker。 以下是一些步骤来注销 Service Worker: 获取 Service Worker 的注册:

  1. 首先,你需要获取当前已注册的 Service Worker。你可以使用 navigator.serviceWorker.getRegistration() 方法来获取 Service Worker 的注册对象。这将返回一个 Promise,包含 Service Worker 的注册信息。
scss 复制代码
navigator.serviceWorker.getRegistration()
  .then((registration) => {
    if (registration) {
      // 在这里执行注销操作
      // 一旦你获取到 Service Worker 的注册信息,你可以使用 `unregister()` 方法来注销它。
    }
  });
  1. 注销 Service Worker:
javascript 复制代码
navigator.serviceWorker.getRegistration()
  .then((registration) => {
    if (registration) {
      registration.unregister()
        .then((isUnregistered) => {
          if (isUnregistered) {
            console.log('Service Worker unregistered successfully.');
          } else {
            console.log('Service Worker was not unregistered.');
          }
        })
        .catch((error) => {
          console.error('Error while trying to unregister the Service Worker:', error);
        });
    }
  });

Service Worker 调试以及检查

javascript 复制代码
 service worker实际上提供的是本地缓存服务,所以和我们平时查看localStorage差不多,打开谷歌浏览
 器调试中心,在Application栏下,就能看到Service Woerkers,如图:

也可以通过右侧 取消注册 以及更新 进行手动触发

我们可以通过网络请求看到当前请求的一个状态

Service Worker 和其他缓存(如浏览器缓存、Web Storage、IndexedDB 等)之间有一些关键区别

  1. 位置

    • Service Worker 是一个在浏览器后台运行的 JavaScript 脚本,它能够拦截和处理网络请求,以及缓存响应数据。它通常用于实现离线缓存、推送通知和其他高级功能。
    • 浏览器缓存Web StorageIndexedDB 等是在浏览器前台运行的缓存机制,它们通常用于存储静态资源(如图片、CSS、JavaScript)、用户数据和应用程序状态。
  2. 用途

    • Service Worker 的主要目的是提供离线支持、网络请求拦截、推送通知和后台同步等功能,从而增强 Web 应用程序的性能和用户体验。
    • 浏览器缓存 用于存储静态资源,以减少资源加载时间和带宽消耗。
    • Web StorageIndexedDB 通常用于存储应用程序的用户数据、会话信息和应用程序状态。
  3. 网络请求控制

    • Service Worker 具有强大的网络请求控制能力,它可以拦截和处理网络请求,从缓存中获取响应,甚至将请求代理到服务器。
    • 浏览器缓存 通常依赖于浏览器的默认缓存策略,但可以通过 HTTP 标头进行控制。
    • Web StorageIndexedDB 不直接与网络请求相关,而是用于本地存储数据。
  4. 离线支持

    • Service Worker 是设计用来提供离线支持的,它可以使网页在离线状态下仍然能够运行。
    • 浏览器缓存 通常缓存静态资源,但不提供离线支持。
    • Web StorageIndexedDB 也不提供离线支持,它们依赖于浏览器的在线状态。
  5. 事件驱动

    • Service Worker 是事件驱动的,它可以响应网络请求、推送通知和其他事件。

    • 浏览器缓存Web StorageIndexedDB 不是事件驱动的,它们通常需要手动操作来读取和写入数据

    总的来说,Service Worker 是一个强大的工具,可用于增强 Web 应用程序的性能和功能,特别是在离线和实时通知方面。其他缓存机制通常用于存储静态资源和用户数据,但它们不提供 Service Worker 的高级功能。在开发 Web 应用程序时,你可以根据需求选择合适的缓存机制。

相关推荐
轻口味16 分钟前
【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
前端·华为·harmonyos
alikami18 分钟前
【若依】用 post 请求传 json 格式的数据下载文件
前端·javascript·json
吃杠碰小鸡1 小时前
lodash常用函数
前端·javascript
emoji1111111 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
泰伦闲鱼1 小时前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs
m0_748250031 小时前
Web 第一次作业 初探html 使用VSCode工具开发
前端·html
一个处女座的程序猿O(∩_∩)O1 小时前
vue3 如何使用 mounted
前端·javascript·vue.js
m0_748235951 小时前
web复习(三)
前端
AiFlutter1 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
麦兜*1 小时前
轮播图带详情插件、uniApp插件
前端·javascript·uni-app·vue