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

如何为Nuxt 3搭配vite-pwa添加自定义Service Worker?

Nuxt 3 + @vite-pwa/nuxt 自定义Service Worker与推送通知解决方案

针对你的困惑逐一解答:

1. 自定义Service Worker实现推送的思路是否正确?

完全正确。无需依赖OneSignal这类第三方服务,通过编写自定义Service Worker,结合浏览器的Notification API(展示通知)、Push API(服务器触发推送)或Periodic Background Sync API(定时本地触发推送),就能实现用户离线/未打开应用时的通知推送。

注意:浏览器强制要求通知必须是用户可见的,所以配置推送订阅时userVisibleOnly必须设为true;另外Periodic Background Sync目前仅Chrome、Edge等Chromium内核浏览器支持,如需更广兼容性,建议结合服务器主动推送方案。

2. dev-sw.js的注册逻辑为何没在源码中找到?

开发环境下,@vite-pwa/nuxt会通过Nuxt内部插件逻辑动态注入Service Worker注册脚本,而非直接写入静态HTML源码。你可以在浏览器Elements标签页的<head>区域找到动态添加的注册脚本;dev-sw.js是模块为开发环境生成的临时Service Worker,用于缓存调试,生产环境会替换为你自定义的文件。

3. 如何配置injectManifest模式?

在nuxt.config.ts的PWA配置中指定strategy: 'injectManifest',并自定义Service Worker的路径即可,示例配置如下:

export default defineNuxtConfig({
  modules: ['@vite-pwa/nuxt'],
  pwa: {
    strategy: 'injectManifest',
    srcDir: 'public', // 自定义Service Worker所在目录
    filename: 'sw.js', // 你的自定义Service Worker文件名
    injectRegister: 'script', // 生产环境会自动在HTML头部注入注册脚本
    manifest: {
      // 你的PWA Manifest配置(图标、名称等)
      name: 'My Nuxt PWA',
      short_name: 'Nuxt PWA',
      start_url: '/',
      display: 'standalone',
      background_color: '#ffffff',
      theme_color: '#41b883',
      icons: [
        {
          src: '/icons/icon-192x192.png',
          sizes: '192x192',
          type: 'image/png'
        }
      ]
    },
    workbox: {
      skipWaiting: true, // 新Service Worker激活后立即接管页面
      clientsClaim: true
    }
  }
})

自定义Service Worker实现推送的完整步骤

1. 编写自定义Service Worker文件

在public目录下创建sw.js,添加推送相关逻辑:

// 监听服务器推送事件
self.addEventListener('push', (event) => {
  const data = event.data?.json() || { title: '系统通知', body: '你有一条新消息' }
  const options = {
    body: data.body,
    icon: '/icons/icon-192x192.png',
    badge: '/icons/badge-72x72.png',
    data: { url: data.url || '/' }
  }

  event.waitUntil(
    self.registration.showNotification(data.title, options)
  )
})

// 监听通知点击事件
self.addEventListener('notificationclick', (event) => {
  event.notification.close()
  event.waitUntil(
    clients.openWindow(event.notification.data.url)
  )
})

// 注册定时同步任务(示例:24小时触发一次)
async function registerPeriodicSync() {
  try {
    await self.registration.periodicSync.register('periodic-notification', {
      minInterval: 24 * 60 * 60 * 1000
    })
  } catch (err) {
    console.log('定时同步注册失败:', err)
  }
}

self.addEventListener('activate', (event) => {
  event.waitUntil(registerPeriodicSync())
})

// 处理定时同步事件
self.addEventListener('periodicsync', (event) => {
  if (event.tag === 'periodic-notification') {
    event.waitUntil(
      // 可在此请求后端获取最新通知内容,再触发推送
      fetch('/api/get-notification')
        .then(res => res.json())
        .then(data => {
          if (data.title && data.body) {
            self.registration.showNotification(data.title, { body: data.body })
          }
        })
    )
  }
})

2. 客户端请求通知权限并注册推送订阅

在plugins目录创建pwa.client.ts(仅在客户端运行):

export default defineNuxtPlugin(async () => {
  if ('serviceWorker' in navigator && 'PushManager' in window) {
    const registration = await navigator.serviceWorker.ready
    // 请求用户通知权限
    const permission = await Notification.requestPermission()
    if (permission === 'granted') {
      // 生成推送订阅(需替换为你的VAPID公钥)
      const subscription = await registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: '你的VAPID公钥'
      })
      // 将订阅信息发送到后端保存,用于服务器主动推送
      await fetch('/api/save-subscription', {
        method: 'POST',
        body: JSON.stringify(subscription),
        headers: { 'Content-Type': 'application/json' }
      })
    }
  }
})

3. 生成VAPID密钥对

使用web-push库生成密钥对(用于服务器与客户端的推送鉴权):

  1. 安装依赖:npm install web-push
  2. 生成密钥:
const webpush = require('web-push')
const vapidKeys = webpush.generateVAPIDKeys()
console.log('VAPID公钥:', vapidKeys.publicKey)
console.log('VAPID私钥:', vapidKeys.privateKey)

将公钥填入客户端代码,私钥保存在后端用于发送推送请求。

内容的提问来源于stack exchange,提问作者Moglash

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:40:00