ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

缓存与离线存储

缓存与离线存储 5.3 缓存与离线存储缓存与离线存储是提升Web应用加载性能、实现断网可用的核心技术体系。不同于Web Storage的纯业务数据存储Cache Storage专注于HTTP网络资源的可编程缓存配合运行在浏览器后台的Service Worker线程可以实现对网络请求的拦截与自定义响应进而构建完整的离线应用。这套体系也是PWA渐进式Web应用的核心技术底座能够让Web应用具备接近原生应用的加载速度与离线可用性。5.3.1 Cache Storage 基础Cache Storage 是浏览器原生提供的请求-响应对式资源缓存系统专门用于存储HTTP请求与对应的响应资源支持精细化的可编程缓存控制。它是异步API不阻塞主线程既可以在主线程访问也可以在Service Worker等Worker线程中使用是资源级缓存的核心载体。一、核心特性存储结构以Request对象为键Response对象为值完整存储HTTP请求与响应的全部头信息与数据体可编程控制完全由开发者控制缓存的增删改查、匹配规则与淘汰策略不受浏览器默认HTTP缓存机制限制异步非阻塞所有操作均基于Promise异步执行不会阻塞页面主线程同源隔离严格遵循同源策略不同站点的缓存互相独立、不可互访二、核心操作语法// 1.打开/创建名为 v1 的缓存库不存在则新建const cache await caches.open(v1);// 2.批量缓存静态资源await cache.addAll([/index.html,/styles/main.css,/js/app.js,/images/logo.png]);// 3.匹配请求获取缓存响应const response await caches.match(/index.html);if (response) {console.log(命中缓存);}// 4.删除指定缓存条目await cache.delete(/old-resource.js);// 5.删除整个旧版本缓存库await caches.delete(v0);// 6.获取所有缓存库名称用于版本管理const cacheNames await caches.keys();三、与浏览器 HTTP 缓存的区别对比维度HTTP 缓存Cache Storage控制主体浏览器自动控制通过服务端响应头配置开发者完全可编程控制缓存粒度按请求自动缓存策略单一可自定义缓存范围、更新时机、淘汰逻辑离线可用性依赖缓存头配置离线支持弱可自定义全链路离线策略完全支持离线访问操作能力仅被动读取无法主动管理支持主动增删改查、多版本管理、精准匹配5.3.2 Service Worker 缓存机制入门Service Worker 是运行在浏览器后台的独立Worker线程独立于网页主线程具备网络请求拦截、缓存操作、后台同步的能力。它是连接网络层与缓存层的核心枢纽通过拦截页面的所有网络请求结合Cache Storage实现自定义的缓存策略是离线应用的核心引擎。一、核心生命周期缓存相关阶段Service Worker拥有独立的生命周期其中与缓存直接相关的是安装、激活、运行三个阶段安装阶段Install首次注册时触发用于预缓存核心静态资源应用壳是离线可用的基础激活阶段Activate安装完成后触发用于清理旧版本缓存、完成缓存版本迭代运行阶段Active激活后持续运行通过fetch事件拦截所有网络请求执行缓存策略二、基础实现代码1. 主线程注册 Service Worker//主线程中注册if (serviceWorker in navigator) {navigator.serviceWorker.register(/sw.js).then(reg console.log(注册成功作用域, reg.scope)).catch(err console.log(注册失败, err));}2. 安装阶段预缓存静态资源// sw.js内部self.addEventListener(install, event {// waitUntil确保安装过程等待缓存操作完成event.waitUntil(caches.open(app-v1).then(cache {//预缓存应用核心静态资源return cache.addAll([/,/index.html,/styles/app.css,/js/app.js,/offline.html]);}));//跳过等待直接激活新的Service Workerself.skipWaiting();});3. 激活阶段清理旧版本缓存self.addEventListener(activate, event {event.waitUntil(caches.keys().then(cacheNames {//删除所有非当前版本的旧缓存return Promise.all(cacheNames.filter(name name ! app-v1).map(name caches.delete(name)));}));//立即接管所有打开的页面self.clients.claim();});4. 运行阶段拦截请求执行缓存策略self.addEventListener(fetch, event {event.respondWith(//先查找缓存命中则直接返回否则发起网络请求caches.match(event.request).then(cachedResponse {return cachedResponse || fetch(event.request);}));});三、常见缓存策略策略核心逻辑适用场景缓存优先Cache First优先返回缓存缓存不存在再请求网络静态资源、不常变化的资源加载速度最快网络优先Network First优先请求网络网络失败再返回缓存动态数据、经常更新的内容保证数据新鲜度仅缓存Cache Only只从缓存获取不发起任何网络请求纯离线资源、预缓存的应用壳仅网络Network Only只发起网络请求不使用缓存实时性要求极高的接口、敏感操作注意Service Worker 必须运行在HTTPS协议下本地localhost开发环境除外作用域为脚本所在路径及其子路径且无法直接访问页面DOM。5.3.3 离线应用基础离线应用是指在网络断开、网络不稳定的场景下依然能够正常加载页面、展示内容、支持基础操作的Web应用。基于Service Worker Cache Storage的组合Web应用可以摆脱对实时网络的依赖具备接近原生应用的可用性。一、核心设计模型应用壳模型App Shell业界通用的离线应用设计思路将应用拆分为两层应用壳应用的基础UI框架、核心静态资源HTML、CSS、核心JS、基础图标体积小、不常变化。在Service Worker安装阶段预缓存离线时直接从缓存加载保证秒开与离线可用。动态内容业务数据、动态接口内容根据网络状态选择加载策略。网络正常时实时更新离线时展示缓存数据或友好降级提示。二、离线应用核心能力离线页面访问预缓存的页面与静态资源断网时可正常加载渲染离线数据展示缓存的历史接口数据断网时展示最近一次的有效内容离线操作暂存用户提交的操作通过Web Storage或IndexedDB暂存本地网络恢复后自动同步离线降级提示完全不可用的场景展示预缓存的友好离线提示页面三、基础实现步骤资源分层划分静态核心资源与动态业务资源分别设计对应的缓存策略预缓存应用壳Service Worker安装阶段缓存核心静态资源保证基础页面离线可访问请求分层拦截静态资源使用缓存优先策略动态接口使用网络优先离线降级离线兜底页面请求失败时返回预缓存的离线提示页面数据同步离线操作暂存本地监听online事件网络恢复后执行批量同步四、离线兜底示例// sw.js中页面请求网络失败时返回离线页面self.addEventListener(fetch, event {//仅处理页面导航请求if (event.request.mode navigate) {event.respondWith(fetch(event.request).catch(() {//网络失败返回离线兜底页面return caches.match(/offline.html);}));}});五、能力边界仅预缓存的资源可离线访问未缓存的动态资源与接口无法加载离线写入操作需要额外设计数据暂存与冲突同步机制缓存总容量受浏览器存储配额限制大体积资源需谨慎缓存
返回列表