离线功能详解

深入了解PWA离线支持的技术实现

Service Worker 工作原理

Service Worker 是运行在浏览器后台的脚本,独立于网页主线程,能够拦截网络请求、管理缓存,并提供离线功能支持。

核心特性

  • 网络代理:拦截所有网络请求
  • 缓存管理:智能缓存策略
  • 后台同步:离线数据同步
  • 推送通知:后台消息处理

生命周期

1
注册 (Register)
2
安装 (Install)
3
激活 (Activate)
4
运行 (Fetch)

缓存策略

Cache First

优先从缓存获取资源,适用于静态资源

// 缓存优先策略 if (cache.has(request)) { return cache.match(request); } else { return fetch(request); }

Network First

优先从网络获取,失败时使用缓存

// 网络优先策略 try { const response = await fetch(request); return response; } catch { return cache.match(request); }

Stale While Revalidate

返回缓存,同时更新缓存

// 后台更新策略 const cachedResponse = cache.match(request); const fetchPromise = fetch(request); return cachedResponse || fetchPromise;

Cache Only

仅使用缓存,适用于离线模式

// 仅缓存策略 return cache.match(request) || new Response('离线内容不可用');

Service Worker 代码示例

1. 注册 Service Worker

// 在主线程中注册 if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/service-worker.js') .then(registration => { console.log('SW 注册成功:', registration.scope); }) .catch(error => { console.log('SW 注册失败:', error); }); }

2. 安装事件处理

// service-worker.js const CACHE_NAME = 'pwa-cache-v1'; const urlsToCache = [ '/', '/styles.css', '/script.js', '/offline.html' ]; self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME) .then(cache => cache.addAll(urlsToCache)) ); });

3. 拦截网络请求

self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(response => { // 缓存命中,返回缓存 if (response) { return response; } // 缓存未命中,发起网络请求 return fetch(event.request); }) ); });

离线体验优化

预缓存关键资源

在安装时缓存核心文件,确保离线可用

优雅降级

提供离线页面,告知用户当前状态

后台同步

网络恢复时自动同步离线数据

页面导航测试

测试三级页面的导航功能:

当前导航状态

当前页面:

历史长度:

来源页面: