你网站的网速是很快,但是在没有网络的情况下你怎么办?🐒🐒🐒

在现代的网络世界里,5G 网络的普及,我们可以访问一个网站或者使用一个 App 的速度极其快,但是在没有网络的情况下你啥都看不了,只能大眼瞪小眼了。

离线应用是指通过离线缓存技术,让资源在第一次被加载后缓存在本地,下次访问它时就直接返回本地的文件,就算没有网络连接。

通过离线应用,主要有以下几个优点:

  1. 在没有网络的情况下也能打开网页。
  2. 由于部分被缓存的资源直接从本地加载,对用户来说可以加速网页加载速度,对网站运营者来说可以减少服务器压力以及传输流量费用。

离线应用的核心是离线缓存技术,要实现这种方式,我们可以使用 Service Worker 来实现这种缓存技术。

什么是 Service Worker

Service Worker 服务器和浏览器之间的之间的桥梁或者中间人。

Service Worker 运行在一个与页面 JavaScript 主线程独立的线程上,并且无权访问 DOM 结构。但是它能拦截当前网站所有的请求,对请求使用相应的逻辑进行判断,如果需要向服务器发起请求的就转给服务器,如果可以直接使用缓存的就直接返回缓存不再转给服务器。从而大大提高浏览体验。

注册 Service Worker

要使用 Service Worker,首先我们要判断浏览器是否支持 Service Worker,具体代码逻辑如下:

js 复制代码
if (navigator.serviceWorker) {
  window.addEventListener("DOMContentLoaded", function () {
    navigator.serviceWorker.register("/worker.js");
  });
}

这段代码的主要目的是在支持 Service Worker 的浏览器中,当页面加载完成后注册一个指定的 Service Worker 脚本。这个传入的 worker.js 就是 Service Worker 的运行环境。

这个脚本被安装到浏览器中后,就算用户关闭了当前网页,它仍会存在。 也就是说第一次打开该网页时 Service Workers 的逻辑不会生效,因为脚本还没有被加载和注册,但是以后再次打开该网页时脚本里的逻辑将会生效。

Service Worker 安装和激活

注册完成后,worker.js 文件会自动下载、安装,然后激活。它提供了一些 API 给我们做一些监听事件:

js 复制代码
self.addEventListener("install", function (e) {
  console.log("Service Worker 安装成功");
});

self.addEventListener("fetch", function (event) {
  console.log("service worker is fetch");
});

当 install 完成并且成功激活之后,就能够监听 fetch 操作了,如上代码所示,输出结构如下图所示:

使用 Service Workers 实现离线缓存

在上面的内容我们已经知道了 Service Workers 在注册成功后会在其生命周期中派发出一些事件,通过监听对应的事件在特点的时间节点上做一些事情。

在 Service Workers 安装成功后会派发出 install 事件,需要在这个事件中执行缓存资源的逻辑,实现代码如下:

js 复制代码
// 当前缓存版本的唯一标识符,用当前时间代替
const cacheKey = new Date().toISOString();

// 需要被缓存的文件的 URL 列表
const cacheFileList = ["/index.html", "/index.js", "/index.css"];

// 监听 install 事件
self.addEventListener("install", function (event) {
  // 等待所有资源缓存完成时,才可以进行下一步
  event.waitUntil(
    caches.open(cacheKey).then(function (cache) {
      // 要缓存的文件 URL 列表
      return cache.addAll(cacheFileList);
    })
  );
});

在 install 阶段我们就已经指定了要被缓存的内容了,那么就可以在 fetch 阶段中听网络请求事件去拦截请求,复用缓存,代码如下:

js 复制代码
self.addEventListener("fetch", function (event) {
  event.respondWith(
    // 去缓存中查询对应的请求
    caches.match(event.request).then(function (response) {
      // 如果命中本地缓存,就直接返回本地的资源
      if (response) {
        return response;
      }
      // 否则就去用 fetch 下载资源
      return fetch(event.request);
    })
  );
});

通过上面的操作,创建和添加了一个缓存的库,如下图所示:

缓存更新

线上的代码有时需要更新和重新发布,如果这个文件被离线缓存了,那就需要 Service Workers 脚本中有对应的逻辑去更新缓存。

这可以通过更新 Service Workers 脚本文件做到,浏览器针对 Service Worker 有如下机制:

  1. 每次打开接入了 Service Workers 的网页时,浏览器都会去重新下载 Service Workers 脚本文件,如果发现和当前已经注册过的文件存在字节差异,就将其视为新服务工作线程。
  2. 新 Service Workers 线程将会启动,且将会触发其 install 事件。
  3. 当网站上当前打开的页面关闭时,旧 Service Workers 线程将会被终止,新 Service Workers 线程将会取得控制权。
  4. 新 Service Workers 线程取得控制权后,将会触发其 activate 事件。

新 Service Workers 线程中的 activate 事件就是最佳的清理旧缓存的时间点,代码如下:

js 复制代码
var cacheWhitelist = [cacheKey];

self.addEventListener("activate", function (event) {
  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 作为服务器和浏览器两者之间的桥梁,它并且可以缓存技术,通过这种方式,在断网的时候,去获取缓存中相应的数据以展示给客户显示。

当断网之后,直接给他页面返回一个俄罗斯方块让他玩足一整天。

相关推荐
破z晓2 分钟前
OpenLayers 开源的Web GIS引擎 - 地图初始化
前端·开源
好看资源平台11 分钟前
JavaScript 数据可视化:前端开发的核心工具
开发语言·javascript·信息可视化
维生素C++22 分钟前
【可变模板参数】
linux·服务器·c语言·前端·数据结构·c++·算法
vah10127 分钟前
python队列操作
开发语言·前端·python
项目題供诗28 分钟前
尚品汇-H5移动端整合系统(五十五)
java·服务器·前端
会蹦的鱼1 小时前
React学习day07-ReactRouter-抽象路由模块、路由导航、路由导航传参、嵌套路由、默认二级路由的设置、两种路由模式
javascript·学习·react.js
DT——6 小时前
Vite项目中eslint的简单配置
前端·javascript·代码规范
mingzhi616 小时前
网安面试会问到的:http的长连接和短连接
http·面试·职场和发展
极客先躯7 小时前
高级java每日一道面试题-2024年9月16日-框架篇-Spring MVC和Struts的区别是什么?
java·spring·面试·mvc·struts2·框架篇·高级java
学习ing小白8 小时前
JavaWeb - 5 - 前端工程化
前端·elementui·vue