PWA 的缓存策略决定了如何处理网络请求和缓存资源,不同的策略适用于不同的场景。
常见的缓存策略
1. Cache First(缓存优先)
适用场景:静态资源(CSS、JS、图片、字体等)
实现方式:
javascriptself.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(response => { return response || fetch(event.request); }) ); });
优点:
- 响应速度快
- 减少网络流量
- 离线可用
缺点:
- 可能返回过期内容
- 需要手动更新缓存
2. Network First(网络优先)
适用场景:动态内容、API 请求
实现方式:
javascriptself.addEventListener('fetch', event => { event.respondWith( fetch(event.request) .then(response => { // 缓存响应 const responseClone = response.clone(); caches.open('dynamic-cache').then(cache => { cache.put(event.request, responseClone); }); return response; }) .catch(() => { return caches.match(event.request); }) ); });
优点:
- 总是返回最新内容
- 网络失败时有降级方案
缺点:
- 首次加载较慢
- 网络不稳定时体验差
3. Stale While Revalidate(缓存同时更新)
适用场景:需要快速响应但也要保持内容新鲜度的资源
实现方式:
javascriptself.addEventListener('fetch', event => { event.respondWith( caches.match(event.request).then(cachedResponse => { const fetchPromise = fetch(event.request).then(networkResponse => { caches.open('dynamic-cache').then(cache => { cache.put(event.request, networkResponse.clone()); }); return networkResponse; }); return cachedResponse || fetchPromise; }) ); });
优点:
- 快速响应(立即返回缓存)
- 后台更新缓存
- 平衡速度和新鲜度
缺点:
- 实现相对复杂
- 可能短暂显示过期内容
4. Network Only(仅网络)
适用场景:实时数据、支付等敏感操作
实现方式:
javascriptself.addEventListener('fetch', event => { if (event.request.url.includes('/api/realtime')) { event.respondWith(fetch(event.request)); } });
优点:
- 确保数据最新
- 适合实时性要求高的场景
缺点:
- 无法离线使用
- 依赖网络稳定性
5. Cache Only(仅缓存)
适用场景:离线页面、预加载的资源
实现方式:
javascriptself.addEventListener('fetch', event => { if (event.request.url.includes('/offline')) { event.respondWith(caches.match(event.request)); } });
优点:
- 完全离线可用
- 响应速度最快
缺点:
- 需要预先缓存
- 内容可能过期
6. Cache First with Network Fallback(缓存优先,网络降级)
适用场景:需要快速响应,但在缓存失败时尝试网络
实现方式:
javascriptself.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'); }); }) ); });
缓存策略的选择
根据资源类型选择合适的策略:
| 资源类型 | 推荐策略 | 原因 |
|---|---|---|
| 静态资源(CSS、JS、图片) | Cache First | 不常变化,优先速度 |
| API 请求 | Network First | 需要最新数据 |
| HTML 文档 | Network First with Cache Fallback | 需要最新,但可降级 |
| 字体文件 | Cache First | 不常变化,离线可用 |
| 实时数据 | Network Only | 必须最新 |
| 离线页面 | Cache Only | 预缓存,完全离线 |
缓存管理
缓存版本控制
javascriptconst CACHE_VERSION = 'v1'; const CACHE_NAME = `my-app-${CACHE_VERSION}`; self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME).then(cache => { return cache.addAll([ '/', '/styles/main.css', '/scripts/main.js' ]); }) ); }); self.addEventListener('activate', event => { event.waitUntil( caches.keys().then(cacheNames => { return Promise.all( cacheNames.map(cacheName => { if (cacheName !== CACHE_NAME) { return caches.delete(cacheName); } }) ); }) ); });
缓存清理策略
- 定期清理过期缓存
- 按需清理特定资源
- 限制缓存大小
最佳实践
- 混合使用策略:根据不同资源类型使用不同策略
- 设置缓存过期:为缓存设置合理的过期时间
- 监控缓存大小:避免占用过多存储空间
- 提供离线页面:在网络不可用时提供友好的提示
- 测试缓存行为:在不同网络条件下测试缓存策略
- 更新机制:实现自动更新机制确保内容新鲜度