网页离线缓存 Service Worke

news2024/11/16 12:33:06

随着 Web 技术的飞速发展,用户对网站的要求越来越高,为了达到用户期望,开发者使出了浑身解数来做性能优化,包括 CDN 内容分发、图片合并、资源文件压缩、异步加载等等手段,这些手段绝大部分都是在干一件事情,那就是加快资源的加载速度,尽量减少白屏时间。而 service worker 的出现不仅能使页面达到秒开的效果,还能让网站在弱网甚至无网的情况下依然能做出很好的响应。让从前只有原生 APP 才可以做到的离线使用功能。在web页面上也能实现。

Service Worker是什么?

官方解释:Service Worker是一种特殊的 Web worker,是浏览器运行在后台与网页主线程独立的另一个线程,这种工作子线程的出现通常都是为了做一些比较耗费性能的计算,有需要的时候再跟主线程通信,告知主线程它的计算结果,这样将计算和渲染独立开来,从而就避免了阻塞的情况。

通俗理解:

Service Worker 是一种能够在后台运行的独立于网页的脚本,它能够拦截和处理网络请求,然后根据一些条件来决定是请求本地的缓存还是云端的服务,再把请求到的内容写入本地的缓存来管理,所以即使在突然断网的情况下它也能向用户显示内容。

特点

  1. 独立于主线程:运行在独立的线程中,不会阻塞或干扰主线程的运行。

  2. 生命周期:有明确的生命周期,包括安装、激活、运行等状态。

  3. 拦截网络请求:可以拦截网页的网络请求,并通过编程接口处理这些请求,比如返回缓存的数据或发起新的网络请求。

  4. 离线缓存:通过缓存管理,可以让应用在离线状态下仍然能正常工作。

  5. 推送通知:支持接收和展示推送通知,即使用户没有打开相关网页。

  6. 不能直接访问/操作DOM

  7. 需要时直接唤醒,不需要时休眠

Service Worker的生命周期

  1. 安装(Installation):

    浏览器首先下载并解析编译 Service Worker 的脚本文件。一旦解析和编译成功,Service Worker 进入安装阶段。在此阶段,可以通过监听 install 事件来执行初始化操作,例如预加载和缓存资源。

  2. 激活(Activation):

    安装完成后,Service Worker 会被激活。在此阶段,可以监听 activate 事件来执行必要的清理操作,例如删除旧版本的缓存资源。

  3. 运行(Running):

    激活后,Service Worker 持续运行在浏览器后台,等待处理来自网页的请求。它可以拦截和处理网络请求、提供离线支持等。

  4. 终止(Termination):

    当所有包含该 Service Worker 的页面被关闭时,Service Worker 会被终止。浏览器可以根据资源利用情况随时中止它,以节省内存。

Service Worker 的基本用法

1. 注册 Service Worker

首先需要在主线程中注册 Service Worker:

if ('serviceWorker' in navigator) { // 检查浏览器是否支持 Service Worker
  navigator.serviceWorker.register('/service-worker.js') // 注册 Service Worker,并指定文件路径
    .then(function(registration) { // 注册成功时的回调函数
      console.log('Service Worker 注册成功:', registration); // 输出成功信息和注册对象
    })
    .catch(function(error) { // 注册失败时的回调函数
      console.log('Service Worker 注册失败:', error); // 输出错误信息
    });
}

navigator.serviceWorker.register 方法注册 Service Worker 时,可以传递一个可选的 scope 参数。该参数用于配置 Service Worker 的作用范围。

默认情况下,Service Worker 的作用范围是注册它的脚本的同级路径及其所有子路径。例如,若注册脚本的 URL 为 ./serviceWorker.js,则其作用范围为 ./ 路径下的所有页面。当然我们也可以通过配置 scope 参数来调整 Service Worker 的作用范围。但是此参数的值必须以/结尾。我们可以通过配置 { scope: './article/' } ,让 ServiceWorker 只作用于页面路径为 /article/ 以及子路径的页面。

注意: Service Worker 是事件驱动的,它会在特定事件触发时启动并执行相应的逻辑。为了节省内存,Service Worker 在不使用时会被浏览器休眠。一旦被休眠,它不会持久保存任何数据,因此需要在重新启动时重新获取所需的数据。

2. 安装阶段

在 service-worker.js 文件中处理安装事件,通常在此阶段主要的工作内容是缓存常用的资源:包括主页文件、样式表、脚本文件以及其他常用的文件。这样可以确保用户即使在离线状态下,也能够访问这些资源,

self.addEventListener('install', function(event) { // 监听 Service Worker 的安装事件
  event.waitUntil( // 使用 event.waitUntil 来确保 Service Worker 在完成任务前不会终止
    caches.open('my-cache-v1').then(function(cache) { // 打开一个名为 'my-cache-v1' 的缓存空间
      return cache.addAll([ // 将指定的资源列表添加到缓存中
        '/', // 缓存网站的根路径
        '/index.html', // 缓存主页文件
        '/styles.css', // 缓存样式表文件
        '/script.js', // 缓存 JavaScript 脚本文件
        '/image.png' // 缓存图片文件
      ]);
    })
  );
});

3. 激活阶段

在激活阶段,我们可以清理旧的缓存。每当资源更新时,我们都需要清除掉的缓存的数据,以节省存储空间,并确保用户获取到的是最新资源。在 activate 事件中处理缓存的管理,可以防止旧的缓存干扰新的应用逻辑。

self.addEventListener('activate', function(event) { // 监听 Service Worker 的激活事件
  event.waitUntil( // 使用 event.waitUntil 确保任务在 Service Worker 激活前完成
    caches.keys().then(function(cacheNames) { // 获取所有缓存的名称
      return Promise.all( // 等待所有删除旧缓存的操作完成
        cacheNames.filter(function(cacheName) { // 过滤出不是当前版本缓存的名称
          return cacheName !== 'my-cache-v1'; // 当前版本缓存的名称为 'my-cache-v1'
        }).map(function(cacheName) { // 映射每个不需要的缓存名称
          return caches.delete(cacheName); // 删除不再需要的缓存
        })
      );
    })
  );
});
4. 拦截网络请求

我们可以在在 fetch 事件中拦截页面的网络请求并决定如何响应。它可以优先从缓存中查找匹配的资源,如果缓存中有则返回缓存的内容;否则发起网络请求获取资源。这种策略不仅可以提高我们的页面加载速度,还可以在离线的情况下提供给用户展示基本的信息。

self.addEventListener('fetch', function(event) { // 监听页面的网络请求事件
  event.respondWith( // 使用 event.respondWith 来提供自定义的响应
    caches.match(event.request).then(function(response) { // 在缓存中查找请求匹配的资源
      return response || fetch(event.request); // 如果缓存中有匹配的资源,则返回缓存资源;否则发起网络请求
    })
  );
});
5. 推送通知

我们还可以通过Service Worker来处理推送通知,他的优点是即使用户不在网站上也可以收到通知。当收到推送事件时,Service Worker 可以显示一条通知,通知内容可以根据推送数据或默认设置来决定。

self.addEventListener('push', function(event) { // 监听推送通知事件
  const title = '推送通知'; // 定义通知的标题
  const options = { // 定义通知的选项
    body: event.data ? event.data.text() : '您有新消息', // 如果推送消息有数据,使用数据内容作为通知正文;否则显示默认消息
    icon: '/icon.png', // 通知的图标
    badge: '/badge.png' // 通知的徽章图标
  };
  event.waitUntil( // 确保在显示通知前完成任务
    self.registration.showNotification(title, options) // 显示通知
  );
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1988536.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

真人拍摄,还是技术生成?会走路的数字人物到底是谁?

近日,一段数字人视频引发了全网热议,画面中,一个外观与真人无异的女子在说话的同时缓缓走动。这也让不少网友质疑,视频中所出现的会走路的数字人物并非是由技术生成,而是真人拍摄。“数字人不都是固定不动的吗&#xf…

【Linux学习】文件系统 - 揭秘磁盘存储结构与存储原理

🍑个人主页:Jupiter. 🚀 所属专栏:Linux从入门到进阶 欢迎大家点赞收藏评论😊 目录 🍑磁盘文件管理🚀磁盘的机械构成🌌磁盘的物理存储🍑存储原理📕磁盘的逻辑…

XML 发票解析

文章目录 1. xml 类型发票格式2. 数据提取思路2.1 项目结构 3. 提取实现3.1 实体类3.2 提取工具类3.3 controller3.4 service 4. 结果展示 1. xml 类型发票格式 本文解析的xml类型的发票格式如下 2. 数据提取思路 通过遍历xml文件中的标签去获得标签对应的文本 2.1 项目结…

MySQL的简单介绍

文章目录 数据库关系型数据库非关系型数据”数据库的概念和用途MySQL数据库服务器、数据库和表的关系数据库的创建和删除表创建表修改常见的数据类型和约束字符串类型日期和时间类型PRIMARY KEY使用AUTO_INCREMENT使用UNIQUE使用FOREIGN KEY使用 SQL语言基础SQL语言简介SQL分类…

基于Spark的豆瓣书籍推荐系统的设计与实现-计算机毕业设计源码53447

摘要 本论文主要论述了如何基于Spark开发一个豆瓣书籍推荐系统,本系统将严格按照软件开发流程进行各个阶段的工作,面向对象编程思想进行项目开发。在引言中,作者将论述豆瓣书籍推荐系统的当前背景以及系统开发的目的,后续章节将严…

谷粒商城实战笔记-MySQL踩坑记录

文章目录 1, Public Key Retrieval is not allowed问题描述解决办法 2,1044 -Access denied for user root% to database解决方案 1, Public Key Retrieval is not allowed 问题描述 打开DBeaver连接MySQL提示“Public Key Retrieval is no…

大数据信用报告查询有什么作用?怎么选择查询平台?

随着互联网的快速发展,人们的金融行为越来越多地依赖于网络平台。然而,网络上的金融交易存在着一定的风险,为了有效地防范这些风险,金融机构采用了大数据技术进行风险控制,下面,小易大数据平台将详细介绍大…

20240807 每日AI必读资讯

👨‍💼马斯克再发难、OpenAI 高层巨变:两大核心人物离职,总裁休长假到年底 - OpenAI 联合创始人 John Schulman 官宣离职,加入原是竞品公司的 Anthropic - 陪伴 OpenAI 共同成长 9 年的总裁兼联合创始人 Greg Brockm…

《计算机组成原理》(第3版)第3章 系统总线 复习笔记

第3章 系统总线 一、总线的基本概念 总线是连接多个部件的信息传输线,是各部件共享的传输介质,如图3-1所示。 图3-1 面向CPU的双总线结构框图 倘若将CPU、主存和I/O设备都挂到一组总线上,便形成单总线结构的计算机,如图3-2所示…

【自动驾驶】ubuntu server安装桌面版

目录 安装桌面版当锁屏界面使用root用户登录错误时 这里环境一开始是ubuntu20.04服务器版本 安装桌面版 sudo apt-get update sudo apt-get upgrade apt-get install -y ubuntu-desktop # 如果你不想安装一些附加的程序,可用以下命令 sudo apt install --no-instal…

java创建多线程方式

文章目录 概要继承 Thread 类实现 Runnable 接口实现 Callable 接口线程池 概要 继承 Thread 类 public class Test extends Thread {Overridepublic void run() {System.out.println("current thread is:" Thread.currentThread().getName());}public static voi…

Aigtek超声功率放大器在建筑结构检测中的应用

超声功率放大器是一种可以可放大交、直流信号的功率放大器。它可以用来驱动高压型负载。通过与主流的信号发生器配套使用,实现信号的放大,因此超声功率放大器在建筑结构检测中有着良好应用,今天Aigtek安泰电子就为大家介绍一下。 什么是超声波…

拓普壹老阳:人力rpo项目如何做才会成功?

为了成功执行老阳推荐的人力RPO项目(招聘流程外包),关键在于几个核心要素的有效整合和执行。RPO项目不仅仅是简单地外包招聘流程,更是通过优化流程、提升效率和质量,帮助企业实现人才招聘的战略目标。 首先,项目的成功与需求分析和…

PID控制算法

关于PID算法最全的文章!从浅入深快速掌握 GitHub - br3ttb/Arduino-PID-Library

STM32F28335:按键实验

一个简单的按键实验: 每一个按键的功能是不一样的 其中不知道为什么key3出现了问题,可是查不出原因,就先放在这里了 按键采用行列扫描的方式判断 大家可以自己看资料 看管脚和资料是程序猿的基本功 代码: key的驱动 keys.c…

【Java】Java泛型、集合、UML统一建模语言、final关键字

昨天在昆仑巢,下午练习Spring Boot的过滤器Filter。 昨天傍晚开始阅读《疯狂Java讲义(第2版)》,熟悉了UML建模语言、Final修饰符、List集合和泛型。 1.UML建模语言: 13种图,常用的包括用例图、类图、组件图、部署图、顺序图、活动图和状态机…

【ai】 时间序列分析的python例子

时间序列分析 :分析和理解随时间变化的数据序列 在gcc的趋势滤波后,需要对排队延迟梯度进行检测及调整,参考的是一个阈值, 调整阈值时就使用了时间序列分析技术: 时间序列分析是统计学和数据分析中的一种技术,用于分析和理解随时间变化的数据序列。时间序列数据具有时间上…

活动易企秀H5场景秀源码系统 带完整的安装代码包以及搭建教程

在数字化营销飞速发展的今天,H5页面以其独特的互动性、高度的传播性和良好的兼容性成为众多企业及个人宣传推广的首选。而“活动易企秀H5场景秀”作为一款广受欢迎的在线H5创作工具,凭借其丰富的模板、简易的操作流程,让非技术背景的用户也能…

MySQL笔记(八):事务

一、事务 事务用于保证数据的一致性,它由一组相关的dml组成,该组的dml语句要么全部成功,要么全部失败:转账。 事务和锁:当执行事务操作时(dml语句),mysql会在表上加锁,防止其他用户…

【Mysql】第十四章 使用C语言链接(环境配置+连接库+sql函数)

文章目录 1.下载库2.上传库3.编译库4.连接库创建对象-mysql_init连接数据库-mysql_real_connect关闭数据库连接-mysql_close 5.sql函数设置编码格式-mysql_set_character_set发送请求-mysql_query获取查询结果-mysql_store_result获取查询结果的行数-mysql_num_rows获取查询结果…