Service Worker缓存策略与离线存储实践概述Service Worker作为现代Web应用的核心技术之一,为开发者提供了强大的网络拦截和缓存控制能力。通过合理配置缓存策略,可以显著提升应用的加载速度和离线使用体验。核心概念Service Worker生命周期Service Worker的生命周期包含以下几个关键阶段:注册阶段:浏览器下载并解析Service Worker脚本安装阶段:触发install事件,进行资源预缓存激活阶段:触发activate事件,清理旧缓存运行阶段:拦截网络请求,实现缓存策略缓存策略类型1. 缓存优先策略 (Cache First)self.addEventListener('fetch', (event) => { event.respondWith( caches.match(event.request) .then((response) => { return response || fetch(event.request); }) ); }); 2. 网络优先策略 (Network First)self.addEventListener('fetch', (event) => { event.respondWith( fetch(event.request) .catch(() => { return caches.match(event.request); }) ); }); 3. 缓存更新策略 (Cache with Network Update)self.addEventListener('fetch', (event) => { event.respondWith( caches.open(CACHE_NAME) .then((cache) => { return cache.match(event.request) .then((response) => { const fetchPromise = fetch(event.request).then((networkResponse) => { cache.put(event.request, networkResponse.clone()); return networkResponse; }); return response || fetchPromise; }); }) ); }); 实践应用基础配置const CACHE_NAME = 'v1'; const urlsToCache = [ '/', '/styles/main.css', '/script/main.js', '/offline.html' ]; // 安装事件 self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_NAME) .then((cache) => { return cache.addAll(urlsToCache); }) ); }); // 激活事件 self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( cacheNames.map((cacheName) => { if (cacheName !== CACHE_NAME) { return caches.delete(cacheName); } }) ); }) ); }); 智能缓存策略// 根据资源类型选择不同策略 self.addEventListener('fetch', (event) => { const { request } = event; const url = new URL(request.url); // API请求使用网络优先 if (url.pathname.startsWith('/api/')) { event.respondWith(networkFirstStrategy(request)); } // 静态资源使用缓存优先 else if (request.destination === 'image' || request.destination === 'style' || request.destination === 'script') { event.respondWith(cacheFirstStrategy(request)); } // 其他请求使用混合策略 else { event.respondWith(staleWhileRevalidateStrategy(request)); } }); // 网络优先策略 async function networkFirstStrategy(request) { try { const networkResponse = await fetch(request); if (networkResponse.ok) { const cache = await caches.open(CACHE_NAME); cache.put(request, networkResponse.clone()); } return networkResponse; } catch (error) { const cachedResponse = await caches.match(request); return cachedResponse || new Response('网络错误', { status: 408 }); } } // 缓存优先策略 async function cacheFirstStrategy(request) { const cachedResponse = await caches.match(request); if (cachedResponse) { return cachedResponse; } try { const networkResponse = await fetch(request); if (networkResponse.ok) { const cache = await caches.open(CACHE_NAME); cache.put(request, networkResponse.clone()); } return networkResponse; } catch (error) { return new Response('资源不可用', { status: 503 }); } } // 缓存更新策略 async function staleWhileRevalidateStrategy(request) { const cache = await caches.open(CACHE_NAME); const cachedResponse = await cache.match(request); const fetchPromise = fetch(request).then((networkResponse) => { if (networkResponse.ok) { cache.put(request, networkResponse.clone()); } return networkResponse; }); return cachedResponse || fetchPromise; } 缓存版本管理// 版本控制 const VERSION = 'v2.0.0'; const CACHE_PREFIX = 'my-app-'; const CACHE_NAME = `${CACHE_PREFIX}${VERSION}`; // 清理旧版本缓存 self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( cacheNames.map((cacheName) => { if (cacheName.startsWith(CACHE_PREFIX) && cacheName !== CACHE_NAME) { return caches.delete(cacheName); } }) ); }) ); }); 性能优化缓存大小控制const MAX_CACHE_SIZE = 50; // MB async function trimCache(cacheName, maxItems) { const cache = await caches.open(cacheName); const requests = await cache.keys(); if (requests.length > maxItems) { const requestsToDelete = requests.slice(0, requests.length - maxItems); await Promise.all(requestsToDelete.map((request) => cache.delete(request))); } } 智能预缓存// 根据用户行为预缓存 self.addEventListener('message', (event) => { if (event.data.type === 'PRECACHE_URLS') { const urlsToPrecache = event.data.urls; event.waitUntil( caches.open(CACHE_NAME) .then((cache) => { return cache.addAll(urlsToPrecache); }) ); } }); 错误处理离线页面处理self.addEventListener('fetch', (event) => { event.respondWith( fetch(event.request) .catch(() => { return caches.match('/offline.html'); }) ); }); 网络超时处理function fetchWithTimeout(request, timeout = 5000) { return Promise.race([ fetch(request), new Promise((_, reject) => setTimeout(() => reject(new Error('Request timeout')), timeout) ) ]); } 最佳实践1. 渐进式增强始终确保Service Worker是渐进式增强,不影响基本功能。2. 缓存策略选择静态资源:缓存优先API请求:网络优先关键资源:缓存更新非关键资源:网络优先3. 版本管理使用语义化版本控制,确保缓存更新的可控性。4. 错误处理完善的错误处理机制,确保离线体验的一致性。5. 性能监控监控缓存命中率和网络性能,持续优化策略。总结Service Worker缓存策略是构建现代Web应用的重要组成部分。通过合理选择和配置缓存策略,可以显著提升应用的性能和用户体验。在实际应用中,需要根据具体的业务需求和资源特性,选择最适合的缓存策略组合。

发表评论 取消回复