外观
PWA Master Skill (Vite Universal PWA Protocol)
技能定位
本技能旨在为任意 Vite 项目(Vue / React / Preact / Svelte / Vanilla)提供标准化的 PWA 离线化改造方案。确保应用具备离线缓存、更新提醒、全平台图标自适应 以及 iOS/Android 安装引导能力。
触发条件
当用户提出以下请求时自动激活:
- "增加 PWA 支持"
- "重构/修复 PWA"
- "执行 PWA 扩展"
标准化工作流 (Phase-based Workflow)
阶段 A: 环境与基建 (Setup)
- 依赖安装:
- 核心依赖:
pnpm add -D vite-plugin-pwa sharp - 关键: 显式安装运行时依赖
pnpm add workbox-window(用于处理 SW 生命周期)。 - 检查: 确认项目根目录锁文件一致性(推荐 pnpm)。
- 核心依赖:
- 类型支持:
- 修改
tsconfig.json或tsconfig.app.json。 - 在
compilerOptions.types中注入通用类型"vite-plugin-pwa/client"。 - 若为 React 项目,额外注入
"vite-plugin-pwa/react";若为 Vue 项目,额外注入"vite-plugin-pwa/vue"。
- 修改
- 资源自动化: 创建
scripts/generate-icons.js,读取public/logo.svg(或项目现有 Logo) 并利用sharp物理生成 192/512 尺寸的 PNG 图标。
阶段 B: 构建配置 (Vite Config)
- 插件集成: 在
vite.config.ts中配置VitePWA插件。 - 更新策略 (Critical):
- 强制使用
registerType: 'prompt'。 - Workbox 配置: 必须显式开启
skipWaiting和clientsClaim,防止新旧 SW 死锁。typescriptworkbox: { cleanupOutdatedCaches: true, clientsClaim: true, // 让新 SW 立即接管页面 skipWaiting: true // 允许新 SW 跳过等待期 }
- 强制使用
- Manifest 规范:
- 开启
includeAssets包含favicon.ico,logo.svg等资源。 icons配置必须包含 standard (192/512) 和purpose: 'any maskable'(自适应) 图标。
- 开启
阶段 C: 运行时与 UI (Runtime & Components)
- 引导组件: 创建
PWAPrompt组件。- 智能安装检测:
- 利用
window.matchMedia('(display-mode: standalone)').matches判断是否已在 PWA 模式运行。 - 规则: 如果已是 Standalone 模式,严禁显示安装提示(Install Banner),仅保留版本更新提示。
- 利用
- 更新防抖 (Debounce & Loading):
- 点击"更新"按钮后,必须立即将按钮设为
disabled或loading状态。 - UI 文案从"立即更新"变为"正在更新...",防止用户重复点击。
- 兜底: 若 5秒内未触发页面刷新,提示用户"请手动刷新"。
- 点击"更新"按钮后,必须立即将按钮设为
- 核心逻辑 (Vue/React): 必须监听
controllerchange事件以确保页面刷新。单纯调用updateServiceWorker()在某些浏览器可能不会触发重载。javascript// 鲁棒的刷新逻辑示例 const isUpdating = ref(false) const handleUpdate = async () => { isUpdating.value = true // 1. 立即上锁 if (navigator.serviceWorker.controller) { // 2. 监听变化,准备刷新 navigator.serviceWorker.addEventListener('controllerchange', () => { window.location.reload() }) } // 3. 执行更新 (会触发 skipWaiting) await updateServiceWorker(true) } - iOS 特配: 检测 iOS 环境,显示"添加到主屏幕"的手动引导(iOS Safari 不支持自动安装事件)。
- 智能安装检测:
- 全局注入: 将组件挂载到应用的最顶层(
App.tsx或App.vue)。 - 版本生效检验:
- 在
vite.config.ts中通过define注入构建版本常量:__APP_VERSION__: JSON.stringify(pkg.version) - 应用启动时在入口文件(
main.tsx或main.ts)对比当前版本与localStorage.getItem('pwa_last_version') - 若版本不同,弹出提示:
已更新到新版本 vX.X.X(之前 vY.Y.Y) - 更新
localStorage.setItem('pwa_last_version', __APP_VERSION__)
- 在
关键技术规范
- 框架无关性: 代码逻辑应适配当前项目的技术栈。
- UI/UX: 必须包含 iOS 用户的安装指引;已安装用户不打扰;更新过程有反馈。
- 防死锁机制: 必须包含
clientsClaim: true和controllerchange监听,杜绝点击更新后页面无反应。 - 语言: 所有代码注释、Log 信息、UI 文案必须使用 中文。
验收清单 (Checklist)
- [ ]
pnpm build成功且无 Rollup/Type 错误? - [ ]
public/目录下是否存在物理生成的 PNG 图标 (pwa-192x192.png, pwa-512x512.png)? - [ ]
vite.config.ts中是否包含workbox: { clientsClaim: true, skipWaiting: true }? - [ ] 离线模式下页面是否能正常打开?
- [ ] 关键: PWA 模式(Standalone)启动时,是否不显示"安装应用"提示?
- [ ] 关键: 点击"更新"按钮后,按钮是否立即变灰/显示Loading,且页面最终自动刷新?