You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 16:23:05