基于vite-plugin-pwa自定义/api路由拦截及Service Worker安装事件
Vue PWA自定义Service Worker配置与实现
一、vite.config.ts中的vitePWA配置
要同时保留vite-plugin-pwa默认功能并添加自定义逻辑,需使用injectManifest模式(而非默认的generateSW),配置示例如下:
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { VitePWA } from 'vite-plugin-pwa' export default defineConfig({ plugins: [ vue(), VitePWA({ mode: 'development', // 生产环境改为'production' injectManifest: { swSrc: './src/sw.ts', // 指定自定义Service Worker文件路径 swDest: 'sw.js', // 最终生成的SW文件名 globPatterns: ['**/*.{html,js,css,ico,png,svg}'] // 预缓存资源规则,保留默认即可 }, // 保留vite-plugin-pwa的标准配置,比如manifest信息 manifest: { name: 'Frenemy App', short_name: 'Frenemy', start_url: '/', display: 'standalone', background_color: '#ffffff', theme_color: '#41b883', icons: [ // 按需添加图标配置 ] } }) ] })
二、自定义Service Worker逻辑实现
在src/sw.ts文件中,导入vite-plugin-pwa的预缓存逻辑,同时添加自定义的install事件处理和fetch请求拦截:
// 导入workbox预缓存逻辑,保留vite-plugin-pwa的标准缓存功能 import { precacheAndRoute } from 'workbox-precaching' import Dexie from 'dexie' // 处理预缓存资源 precacheAndRoute(self.__WB_MANIFEST) // 初始化IndexedDB实例 let db: Dexie | null = null // 自定义install事件处理 self.addEventListener('install', (event) => { try { db = new Dexie("FrenemyDatabase") db.version(1).stores({ friends: `id,name,age`, enemies: `id,name,age` }) // 等待数据库初始化完成后再完成install event.waitUntil(db.open()) // 强制激活新SW(可选,根据需求决定) self.skipWaiting() } catch (e) { event.waitUntil(Promise.reject(e)) } }) // 拦截fetch请求,区分/api和非/api路径 self.addEventListener('fetch', (event) => { const request = event.request // 判断是否为/api开头的请求 if (request.url.startsWith(`${self.location.origin}/api/`)) { event.respondWith(handleApiRequest(request)) } else { // 非/api请求交给默认逻辑处理,保留vite-plugin-pwa的标准功能 event.respondWith(fetch(request)) } }) // 处理/api请求的逻辑示例 async function handleApiRequest(request: Request): Promise<Response> { if (!db) { return new Response('Database not initialized', { status: 500 }) } try { const url = new URL(request.url) const path = url.pathname.replace('/api/', '') // GET请求示例:获取friends列表 if (request.method === 'GET' && path === 'friends') { const friends = await db.friends.toArray() return new Response(JSON.stringify(friends), { headers: { 'Content-Type': 'application/json' } }) } // POST请求示例:添加新friend if (request.method === 'POST' && path === 'friends') { const friendData = await request.json() const id = await db.friends.add(friendData) return new Response(JSON.stringify({ id, ...friendData }), { headers: { 'Content-Type': 'application/json' }, status: 201 }) } // 未匹配到逻辑时, fallback 到网络请求 return fetch(request) } catch (e) { console.error('API request handling failed:', e) return new Response('Request failed', { status: 500 }) } }
注意事项
- 需安装Dexie依赖:执行
npm install dexie @types/dexie支持IndexedDB操作 - 开发环境下,可在Chrome DevTools的Application标签页调试Service Worker状态
- 生产环境需将
mode设置为production,vite-plugin-pwa会自动优化缓存策略
内容的提问来源于stack exchange,提问作者Brent
相关产品推荐
相关产品推荐

