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应用的重要组成部分。通过合理选择和配置缓存策略,可以显著提升应用的性能和用户体验。在实际应用中,需要根据具体的业务需求和资源特性,选择最适合的缓存策略组合。

发表评论 取消回复