网页离线缓存 Service Worke

简介: 网页离线缓存 Service Worke

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

Service Worker是什么?

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

通俗理解:

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

特点

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

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

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

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

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

不能直接访问/操作DOM

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

Service Worker的生命周期

安装(Installation):

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

激活(Activation):

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

运行(Running):

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

终止(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) // 显示通知
  );
});


目录
相关文章
|
26天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
2天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
308 14
|
18天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
5天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
20天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
22天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2584 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
4天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
177 2
|
2天前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
102 65
|
6天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
283 2
|
22天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1580 16
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码