Service Worker 实现网站可离线访问

Service Worker 生命周期

Service Worker 的生命周期包括以下几个阶段:

  • 注册
  • 安装
  • 等待
  • 激活
  • 终止

在等待阶段,新的 Service Worker 需要等待所有控制它的页面(也就是使用它的页面)都被关闭后才能进入激活阶段。这是因为如果在一个页面还在使用旧的 Service Worker 的时候就激活新的 Service Worker,可能会导致问题。

例如,新的 Service Worker 可能会使用一个新的缓存策略,而这个页面可能还在使用旧的缓存策略,这可能会导致缓存的不一致。

等待所有页面都被关闭可以确保在新的 Service Worker 激活时,没有页面还在使用旧的 Service Worker。这样,我们就可以在新的 Service Worker 中自由地更新我们的缓存策略,而不需要担心会影响到正在使用旧的 Service Worker 的页面。

如果你希望新的 Service Worker 在安装完成后立即激活,无需等待所有页面都被关闭,你可以在你的 Service Worker 脚本中调用 self.skipWaiting() 方法。但是,请注意这可能会导致上述的问题。

创建 sw.js

Service Worker 只能控制其所在目录及其子目录下的文件。

例如,如果你将 sw.js 放在 /scripts/ 目录下,那么这个 Service Worker 只能控制 /scripts/ 目录及其子目录下的文件,不能控制其他目录下的文件。

所以如果你希望你的 Service Worker 能控制你的整个站点,那么你应该将其放在项目的根目录

先在 public 目录下创建 sw.js

js 复制代码
const CACHE_NAME = "my-cache-v1";
const defaultCacheUrl = ['/background.webp'];

// 当 Service Worker 被首次注册或者更新时,install 事件会被触发。
self.addEventListener("install", function (event) {
  event.waitUntil(
    caches.open(CACHE_NAME).then(function (cache) {
      console.log("Opened cache");
      return cache.addAll(urlsToCache);
    })
  );
});

// Service Worker 被激活时会触发
self.addEventListener("activate", function (event) {
  var cacheWhitelist = [CACHE_NAME];
  event.waitUntil(
    caches.keys().then(function (cacheNames) {
      return Promise.all(
        cacheNames.map(function (cacheName) {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

注册 Service Worker

在main.js中写上 Service Worker 注册代码

js 复制代码
// main.js
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js').then(function(registration) {
    console.log('Service Worker registered with scope:', registration.scope);
  }).catch(function(error) {
    console.log('Service Worker registration failed:', error);
  });
}

缓存策略

  1. Stale while revalidate:这种策略首先从缓存中获取响应并立即返回,然后在后台从网络获取响应并更新缓存。这种策略适用于可以容忍短暂过期的资源。
  2. Network first, then cache:这种策略首先尝试从网络获取响应,如果网络请求失败,那么它会从缓存中获取响应。这种策略适用于需要实时数据的应用。
  3. Cache first, then network:这种策略首先尝试从缓存中获取响应,如果缓存中没有找到响应,那么它会从网络获取响应。这种策略适用于静态资源,如 CSS 和 JavaScript 文件。

Stale while revalidate

js 复制代码
// 直接从缓存中取,同时会发起网络请求 更新本地缓存,这意味着资源不会立即更新,而是会在发起第二次请求后才是最新的
self.addEventListener("fetch", function (event) {
  event.respondWith(
    caches.open(CACHE_NAME).then(function (cache) {
      return cache.match(event.request).then(function (response) {
        const fetchPromise = fetch(event.request).then(function (networkResponse) {
          cache.put(event.request, networkResponse.clone());
          return networkResponse;
        });

        return response || fetchPromise;
      });
    })
  );
});

ok,现在只要用户访问过一次我的网站,第二次访问时即使没网络也可以访问我的页面了

因为所有文件都被缓存了

上面只实现了一种缓存策略,另外两种后面更新!

相关推荐
广州华水科技15 分钟前
单北斗GNSS在桥梁形变监测中的应用与技术进展分析
前端
我讲个笑话你可别哭啊16 分钟前
鸿蒙ArkTS快速入门
前端·ts·arkts·鸿蒙·方舟开发框架
CherryLee_121018 分钟前
基于poplar-annotation前端插件封装文本标注组件及使用
前端·文本标注
特立独行的猫a25 分钟前
C++轻量级Web框架介绍与对比:Crow与httplib
开发语言·前端·c++·crow·httplib
周航宇JoeZhou27 分钟前
JB2-7-HTML
java·前端·容器·html·h5·标签·表单
代码小库29 分钟前
【课程作业必备】Web开发技术HTML静态网站模板 - 校园动漫社团主题完整源码
前端·html
珹洺36 分钟前
Bootstrap-HTML(二)深入探索容器,网格系统和排版
前端·css·bootstrap·html·dubbo
BillKu36 分钟前
VS Code HTML CSS Support 插件详解
前端·css·html
xixixin_42 分钟前
【React】中 Body 类限定法:优雅覆盖挂载到 body 的组件样式
前端·javascript·react.js
换日线°1 小时前
NFC标签打开微信小程序
前端·微信小程序