PWA离线优先策略:提升用户体验的关键步骤
Progressive Web Apps (PWA) 的离线优先策略是通过Service Worker和Cache API实现的,它允许在没有网络连接时仍然可以访问网站的部分或全部内容。
2500G计算机入门到高级架构师开发资料超级大礼包免费送!
1. 创建Service Worker注册文件(service-worker.js):
self.addEventListener('install', (event) => {event.waitUntil(caches.open('my-cache-v1').then((cache) => {return cache.addAll(['/index.html','/style.css','/script.js',// 添加其他需要预缓存的文件路径]);}));
});self.addEventListener('fetch', (event) => {event.respondWith(caches.match(event.request).then((response) => {if (response) {return response;}return fetch(event.request).then((networkResponse) => {caches.open('my-cache-v1').then((cache) => {cache.put(event.request.url, networkResponse.clone());});return networkResponse;}).catch(() => {// 如果所有尝试都失败,可以返回一个备用响应,比如错误页面return caches.match('/offline.html');});}));
});
2. 注册Service Worker:
在你的主应用中注册Service Worker:
if ('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('/service-worker.js').then((registration) => {console.log('Service Worker registered:', registration);}).catch((error) => {console.error('Service Worker registration failed:', error);});});
}
3. 更新策略:
当有新版本的应用时,需要更新Service Worker和缓存内容。可以在Service Worker中监听activate
事件:
self.addEventListener('activate', (event) => {event.waitUntil(caches.keys().then((cacheNames) => {return Promise.all(cacheNames.filter((cacheName) => cacheName !== 'my-cache-v1').map((cacheName) => caches.delete(cacheName)));}));
});
4. 更新Service Worker:
更新Service Worker时,需要改变Service Worker文件名(如增加版本号),这样浏览器会认为这是新的SW并触发安装过程。
5. 更新Service Worker生命周期管理:
确保在Service Worker更新时,旧版本的Service Worker不会影响用户体验。通常,你可能希望旧版本Service Worker完成所有请求后再关闭:
self.addEventListener('message', (event) => {if (event.data && event.data.type === 'SKIP_WAITING') {self.skipWaiting();}
});
6. 配置manifest文件:
创建一个manifest.json文件,定义应用的元数据和离线图标:
{"short_name": "My App","name": "My Awesome Progressive Web App","icons": [{"src": "icon-192.png","sizes": "192x192","type": "image/png"},{"src": "icon-512.png","sizes": "512x512","type": "image/png"}],"start_url": "/index.html","display": "standalone","background_color": "#ffffff","theme_color": "#000000"
}
在HTML中引用manifest文件:
<link rel="manifest" href="/manifest.json">
7. 离线通知和重新加载提示
当用户离线后重新上线时,可以通过Service Worker发送通知提醒用户重新加载页面以获取更新内容:
self.addEventListener('online', (event) => {clients.matchAll({ type: 'window' }).then((clients) => {clients.forEach((client) => {client.postMessage({ type: 'RELOAD' });});});
});self.addEventListener('message', (event) => {if (event.data && event.data.type === 'RELOAD') {clients.matchAll({ type: 'window' }).then((clients) => {clients.forEach((client) => {if (client.url === self.registration.scope && 'focus' in client) {client.focus();client.reload();}});});}
});
在主应用中监听消息:
navigator.serviceWorker.addEventListener('message', (event) => {if (event.data && event.data.type === 'RELOAD') {alert('网络已恢复,刷新页面获取最新内容。');location.reload();}
});
8. 离线提示和体验
当用户离线时,提供友好的离线页面或提示:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>离线页面</title><style>body {display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;background-color: #f2f2f2;}h1 {font-size: 2rem;color: #333;}</style>
</head>
<body><h1>您已离线,稍后再试。</h1>
</body>
</html>
然后在Service Worker
的fetch
事件中处理:
self.addEventListener('fetch', (event) => {event.respondWith(caches.match(event.request).then((response) => {if (response) {return response;}// 检查网络请求失败的情况return fetch(event.request).catch(() => {// 返回离线页面return caches.match('/offline.html');});}));
});
9. 更新缓存策略
有时你可能希望缓存特定版本的资源,而不是始终使用最新的。这可以通过在Service Worker中添加版本控制来实现:
const CACHE_NAME = 'my-cache-v2';
const urlsToCache = [// ...
];self.addEventListener('install', (event) => {event.waitUntil(caches.open(CACHE_NAME).then((cache) => {return cache.addAll(urlsToCache);}));
});self.addEventListener('fetch', (event) => {event.respondWith(caches.match(event.request).then((response) => {if (response) {return response;}return fetch(event.request).then((networkResponse) => {caches.open(CACHE_NAME).then((cache) => {cache.put(event.request.url, networkResponse.clone());});return networkResponse;});}));
});
10. 使用App Shell架构
App Shell模型是一种常见的PWA设计模式,它提供一个基本的用户界面框架,即使在离线状态下也能加载。App Shell通常包括导航、头部、侧边栏等非动态内容,这样即使在离线时,用户也能看到应用的基本结构。
首先,创建一个App Shell HTML文件(如app-shell.html
),包含基本的布局和样式。然后,在Service Worker中预缓存App Shell:
const appShellUrls = ['/app-shell.html','/app-style.css',// 其他App Shell相关的资源
];self.addEventListener('install', (event) => {event.waitUntil(caches.open('app-shell-cache').then((cache) => {return cache.addAll(appShellUrls);}));
});
在fetch
事件中,优先从缓存中获取App Shell资源:
self.addEventListener('fetch', (event) => {if (event.request.mode === 'navigate') {event.respondWith(caches.match('/app-shell.html'));} else {event.respondWith(caches.match(event.request).then((response) => {if (response) {return response;}return fetch(event.request);}));}
});
11. 使用Service Worker拦截网络请求
Service Worker还可以用于拦截特定类型的网络请求,例如API调用。这使得你可以在离线时返回默认值或存储的响应,以提供一致的用户体验:
self.addEventListener('fetch', (event) => {if (event.request.url.startsWith('https://api.example.com')) {event.respondWith(caches.match(event.request).then((response) => {if (response) {return response;}return fetch(event.request).then((networkResponse) => {caches.open('api-cache').then((cache) => {cache.put(event.request.url, networkResponse.clone());});return networkResponse;});}));} else {// 处理其他非API请求}
});
12. 集成WebSocket支持
如果你的应用使用WebSocket进行实时通信,可以使用workbox-websocket
库在Service Worker中处理WebSocket连接,确保在离线时能够接收和发送消息:
importScripts('https://unpkg.com/workbox-sw@latest/runtime-caching/workbox-sw.prod.v2.js');
importScripts('https://unpkg.com/workbox-websocket@latest/workbox-websocket.prod.v2.js');workbox.webSocket.register('wss://your-websocket-endpoint.com', {onConnect: (client) => {console.log('WebSocket connected:', client);},onClose: (client) => {console.log('WebSocket disconnected:', client);},
});
13. 测试和监控
确保在不同网络条件下测试你的PWA,包括2G、3G和离线状态。可以使用Chrome开发者工具的模拟网络条件功能。同时,使用Lighthouse等工具定期评估PWA的性能和离线体验。
14. 总结
通过这些策略,可以创建一个高度可用且用户体验优秀的PWA,即使在离线或弱网络环境下也能正常工作。PWA的目标是提供接近原生应用的体验,因此持续优化和测试是关键。
2500G计算机入门到高级架构师开发资料超级大礼包免费送!
相关文章:
PWA离线优先策略:提升用户体验的关键步骤
Progressive Web Apps (PWA) 的离线优先策略是通过Service Worker和Cache API实现的,它允许在没有网络连接时仍然可以访问网站的部分或全部内容。 2500G计算机入门到高级架构师开发资料超级大礼包免费送! 1. 创建Service Worker注册文件(se…...

网页提示“非私密连接”是为什么?
网页提示“非私密连接”(英文提示可能是 "Your connection is not private" 或 "Your connection is not secure")主要是因为浏览器无法验证你正试图访问的网站的SSL/TLS证书,或者是证书存在问题,从而无法建立…...

[自动驾驶技术]-8 Tesla自动驾驶方案之硬件(AI Day 2022)
特斯拉在AI Day 2022先介绍了AI编译器,后面又介绍了Dojo的硬件软件,软件部分和AI编译器有部分重叠,本文介绍还是延用AI Day的思路,分为三部分:AI编译和推理,Dojo硬件,Dojo软件。 特斯拉车道检测…...

人力资源管理信息化系统如何支持企业开展管理诊断?
华恒智信人力资源顾问有限公司致力于帮助企业开展人力资源管理方面的各项提升改进工作,在长期的咨询工作中,最常听到企业提到的问题莫过于管理诊断方面的问题,事实上,很多企业在日常工作中,都意识到企业内部存在管理方…...

Cohere继Command-R+之后发布大模型Aya-23,性能超越 Gemma、Mistral 等,支持中文
前言 近年来,多语言大模型(MLLM)发展迅速,但大多数模型的性能依然存在显著差距,尤其是在非英语语言方面表现不佳。为了推动多语言自然语言处理技术的发展,Cohere团队发布了新的多语言指令微调模型家族——…...

身为UI设计老鸟,不学点3D,好像要被潮流抛弃啦,卷起来吧。
当前3D原则在UI设计中运用的越来越多,在UI设计中,使用3D元素可以为界面带来以下几个价值: 增强视觉冲击力:3D元素可以通过立体感和逼真的效果,为界面增添视觉冲击力,使得设计更加生动、吸引人,并…...

【C语言】实现贪吃蛇--项目实践(超详细)
前言: 贪吃蛇游戏大家都玩过吧?这次我们要用C语言来亲手制作一个!这个项目不仅能让我们复习C语言的知识,还能了解游戏是怎么一步步做出来的。我们会一起完成蛇的移动、食物的生成,还有碰撞检测等有趣的部分。准备好了…...

Elasticsearch 分析器的高级用法一(同义词,高亮搜索)
Elasticsearch 分析器的高级用法一(同义词,高亮搜索) 同义词简介分析使用同义词案例 高亮搜索高亮搜索策略unifiedplainvh 同义词 简介 在搜索场景中,同义词用来处理不同的查询词,有可能是想表达相同的搜索目标。 例…...

Python 开心消消乐
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...
mysql - 索引基本知识梳理
mysql索引基本知识梳理 索引介绍 官方介绍索引是帮助MySQL高效获取数据的数据结构, 原理为以空间换时间, mysql的索引采用的是B树的结构 索引的优缺点 优点: 提高查询效率降低数据库IO成本通过索引对数据进行排序, 降低排序成本, 降低CPU消耗 缺点:…...
Nginx SSL/TLS配置:搭建安全的HTTPS网站
随着互联网安全性的日益提升,HTTPS已经成为网站安全通信的标配。Nginx作为一款高性能的HTTP和反向代理服务器,支持SSL/TLS协议,使得我们可以轻松地搭建安全的HTTPS网站。下面,我们将详细介绍如何在Nginx上配置SSL/TLS,…...
echarts 折线图流光效果偏移或不显示
x轴数据需要字符串数组...

Redis数据类型(上篇)
前提:(key代表键) Redis常用的命令 命令作用keys *查看当前库所有的keyexists key判断某个key是否存在type key查看key是什么类型del key 删除指定的keyunlink key非阻塞删除,仅仅将keys从keyspace元数据中删除,真正的…...

VMware虚拟机安装Linux
1.下载Linux的ISO镜像文件 阿里镜像源网站: https://developer.aliyun.com/mirror/ 清华大学镜像源网站: https://mirrors.tuna.tsinghua.edu.cn/本人选择的是:Centos7.9.2009标准版 https://mirrors.tuna.tsinghua.edu.cn/centos/7.9.2009/isos/x86_64/ 标准版&a…...
slurm是什么,怎么用? For slurm和For Pytorch有什么区别和联系?
1.slurm是什么? Slurm(Simple Linux Utility for Resource Management)是一种开源的、用于集群和超级计算机的作业调度系统。它主要用于管理和调度大规模计算任务,使得用户可以有效地利用集群中的计算资源。Slurm提供了一套功能强…...

类和对象【六】友元和内部类
文章目录 友元友元的作用友元的缺点友元函数语法:特点: 友元类语法:特点: 内部类概念特点 友元 友元的作用 友元提供了一种打破封装的方式,有时提供了便利。 友元的主要作用就是打破封装 即可以让一个类的友元函数…...

一点点 cv 经验 1:cv方向、模型评估、输入尺寸、目标检测器设计
一点点 cv 经验 1:cv方向、模型评估、输入尺寸、目标检测器设计 cv 方向Pytorch数据集划分 模型评估误差偏差方差噪声 输入尺寸方法一:让数据适应模型方法二:修改模型适应数据方法三:划分Patch,分别处理 目标检测器结构…...
Java-SpringBoot集成Langchain4j文本嵌入模型实现向量相似度查询
集成Pg数据库并创建vector字段类型 运行pgvector容器 根据需要进行容器目录挂载 docker run --name pgvector \-e POSTGRES_PASSWORD123456 \-p 5432:5432 \-d --platform linux/amd64 ankane/pgvector:latest 进入docker容器并创建vector字段类型 docker exec -it pgvecto…...

正宇软件:引领数字人大新纪元,开启甘肃人大代表履职新篇章
在数字化强国的主旋律之下,政府工作的数字化、智能化转型已成为提升治理效能、增强人民满意度的关键一环。在这个大背景下,正宇软件技术开发有限公司以其卓越的技术实力和丰富的行业经验,成为了政府信息化建设的杰出代表。甘肃省人大代表履职…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门  / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)
Name:3ddown Serial:FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名:Axure 序列号:8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...

CSS3相关知识点
CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...