重构服务工作者逻辑优

This commit is contained in:
jxxghp
2025-07-04 18:32:04 +08:00
parent f6c07a29ce
commit bb70e91277

View File

@@ -1,5 +1,4 @@
import { cleanupOutdatedCaches, precacheAndRoute } from 'workbox-precaching'
import { NavigationRoute, registerRoute } from 'workbox-routing'
declare let self: ServiceWorkerGlobalScope
@@ -8,43 +7,10 @@ cleanupOutdatedCaches()
// self.__WB_MANIFEST is default injection point
precacheAndRoute(self.__WB_MANIFEST)
// 预缓存离线页面
const OFFLINE_PAGE = '/offline.html'
// 离线版本控制 - 递增此版本号将触发install事件并强制更新缓存资源
const OFFLINE_VERSION = 1
const CACHE_NAME = 'mp-offline-cache-v1'
// 安装时缓存离线页面
self.addEventListener('install', event => {
event.waitUntil(
(async () => {
const cache = await caches.open(CACHE_NAME)
await cache.add(OFFLINE_PAGE)
})(),
)
})
// 处理导航请求的离线回退
const navigationHandler = async (params: any) => {
try {
// 尝试从网络获取页面
const response = await fetch(params.request)
return response
} catch (error) {
// 如果网络失败,返回离线页面
const cache = await caches.open(CACHE_NAME)
const offlineResponse = await cache.match(OFFLINE_PAGE)
return offlineResponse || new Response('离线页面不可用', { status: 503 })
}
}
// 注册导航路由排除API请求
registerRoute(
new NavigationRoute(navigationHandler, {
denylist: [/^(\/[\w-]+)*\/api/, /\/offline\.html$/],
}),
)
// 注意静态资源和API的缓存策略已在vite.config.ts中的workbox配置中定义
// 这里只处理离线页面的特殊逻辑
const OFFLINE_URL = '/offline.html'
// 通知选项
const options = {
@@ -140,6 +106,66 @@ async function clearBadge() {
}
}
// 安装事件 - 缓存离线页面
self.addEventListener('install', event => {
console.log('Service Worker install, version:', OFFLINE_VERSION)
event.waitUntil(
(async () => {
const cache = await caches.open(CACHE_NAME)
// 使用 {cache: 'reload'} 确保从网络获取最新的离线页面
// 而不是从HTTP缓存中获取
await cache.add(new Request(OFFLINE_URL, { cache: 'reload' }))
})(),
)
// 强制等待中的Service Worker立即成为活动的Service Worker
self.skipWaiting()
})
// 激活事件
self.addEventListener('activate', event => {
console.log('Service Worker activate')
event.waitUntil(
(async () => {
// 启用导航预载功能以提高性能
if ('navigationPreload' in self.registration) {
await self.registration.navigationPreload.enable()
}
})(),
)
// 告诉活动的Service Worker立即控制页面
self.clients.claim()
})
// Fetch事件 - 处理网络请求和离线回退
self.addEventListener('fetch', event => {
// 只处理HTML页面的导航请求
if (event.request.mode === 'navigate') {
event.respondWith(
(async () => {
try {
// 首先尝试使用navigationPreload响应如果支持
const preloadResponse = await event.preloadResponse
if (preloadResponse) {
return preloadResponse
}
// 总是优先尝试网络请求
const networkResponse = await fetch(event.request)
return networkResponse
} catch (error) {
// 只有在抛出异常时才会触发catch通常是由于网络错误
// 如果fetch()返回4xx或5xx响应码不会触发catch
console.log('网络请求失败,返回离线页面:', error)
const cache = await caches.open(CACHE_NAME)
const cachedResponse = await cache.match(OFFLINE_URL)
return cachedResponse || new Response('离线页面不可用', { status: 503 })
}
})(),
)
}
})
// 监听 push 事件,显示通知
self.addEventListener('push', function (event) {
console.log('notification push')
@@ -180,18 +206,6 @@ self.addEventListener('push', function (event) {
}
})
// 安装
self.addEventListener('install', function (e) {
console.log('worker install')
self.skipWaiting()
})
// 激活
self.addEventListener('activate', function (e) {
console.log('worker activate')
e.waitUntil(self.clients.claim())
})
// 监听通知点击事件
self.addEventListener('notificationclick', function (event) {
console.log('notification click')