关于 pwa-expert
用于构建可安装、支持离线使用的渐进式 Web 应用开发 Skill,涵盖清单、Service Worker 缓存、安装提示、后台同步和更新流程,也介绍 Next.js 方案。
主要功能
- 01配置 Web App Manifest
- 02注册 Service Worker 并设置缓存
- 03处理安装提示
- 04离线回退与状态模式
- 05后台同步与更新流程
- 06Next.js PWA 方案
适用场景
- 01让 Web 应用可安装
- 02缓存资源以供离线使用
- 03将操作排队并在联网后执行
- 04通知用户应用有可用更新
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ curiositech/ some_claude_skills --skill pwa-expert安装后在 Claude Code 中输入/pwa-expert确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.claude-plugin/plugin.jsonreferences/nextjs-integration.mdservice-worker-patterns.mdbackground-sync.mdinstall-prompt.mdupdate-flow.mdoffline-handling.md详细介绍
渐进式 Web 应用专家
使用 Service Worker、智能缓存和类原生体验,构建可安装、支持离线的 Web 应用。
何时使用此技能
- 让 Web 应用可在移动端/桌面端安装
- 实现离线功能
- 设置 Service Worker 缓存策略
- 处理安装提示(
beforeinstallprompt) - 为离线优先应用实现后台同步
- 管理 PWA 更新流程
- 创建 Web 应用清单
何时不使用此技能
- 原生应用开发 → 使用 React Native、Flutter 或原生 SDK
- 通用 Web 性能优化 → 使用 Lighthouse/性能审计工具
- 服务端渲染问题 → 查阅 Next.js/框架专用文档
- 仅需推送通知 → 考虑专用推送通知服务
- 简单静态网站 → PWA 的额外开销可能不值得
核心概念
PWA 可安装的条件
- HTTPS(开发环境可使用 localhost)
- 包含必需字段的 Web 应用清单
- 带有 fetch 处理程序的 Service Worker
- 图标(最小尺寸为 192×192 和 512×512)
PWA 技术栈
┌─────────────────────────────────────────┐
│ Your App (React/Next.js) │
├─────────────────────────────────────────┤
│ Service Worker (sw.js) │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Cache │ │ Network Fetch │ │
│ │ Storage │ │ Handling │ │
│ └─────────────┘ └─────────────────┘ │
├─────────────────────────────────────────┤
│ manifest.json │
│ (App identity, icons, display mode) │
└─────────────────────────────────────────┘
Web 应用清单
完整的 manifest.json
{
"name": "Junkie Buds 4 Life",
"short_name": "JB4L",
"description": "Recovery support app",
"start_url": "/",
"scope": "/",
"display": "standalone",
"orientation": "portrait-primary",
"background_color": "#1a1410",
"theme_color": "#1a1410",
"icons": [
{
"src": "/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/icons/icon-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/icons/icon-maskable-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
],
"shortcuts": [
{
"name": "Find Meetings",
"short_name": "Meetings",
"url": "/meetings?source=shortcut",
"icons": [{ "src": "/icons/meetings-96.png", "sizes": "96x96" }]
}
]
}
显示模式
| 模式 | 描述 |
|---|---|
fullscreen | 无浏览器界面,全屏显示 |
standalone | 类似应用的体验,无 URL 栏(推荐) |
minimal-ui | 显示部分浏览器控件 |
browser | 普通浏览器标签页 |
在 HTML 中添加链接
<head>
<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#1a1410" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link rel="apple-touch-icon" href="/icons/apple-touch-icon.png" />
</head>
Service Worker 基础知识
注册
// lib/pwa.ts
export async function registerServiceWorker() {
if ('serviceWorker' in navigator) {
try {
const registration = await navigator.serviceWorker.register('/sw.js', {
scope: '/',
});
return registration;
} catch (error) {
console.error('SW registration failed:', error);
}
}
}
// Call on app mount
useEffect(() => {
registerServiceWorker();
}, []);
Service Worker 基本结构
// public/sw.js
const CACHE_NAME = 'myapp-v1';
const STATIC_ASSETS = ['/', '/offline', '/manifest.json'];
// Install: Cache static assets
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => cache.addAll(STATIC_ASSETS))
);
self.skipWaiting();
});
// Activate: Clean old caches
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) =>
Promise.all(keys.filter((k) => k !== CACHE_NAME).map((k) => caches.delete(k)))
)
);
self.clients.claim();
});
// Fetch: Handle requests (see references for strategies)
self.addEventListener('fetch', (event) => {
event.respondWith(handleFetch(event.request));
});
参见:
references/service-worker-patterns.md,了解缓存策略实现
缓存策略
| 策略 | 适用场景 | 权衡 |
|---|---|---|
| Cache-First | 静态资源、字体、图片 | 缓存更新前内容会过时 |
| Network-First | API 数据、用户内容 | 速度较慢,需要网络连接 |
| Stale-While-Revalidate | 兼顾内容新鲜度和速度 | 在后台更新 |
| Network-Only | 身份验证、实时数据 | 不支持离线 |
| Cache-Only | 版本化资源 | 永不更新 |
参见:
references/service-worker-patterns.md,查看完整实现
安装提示
处理 beforeinstallprompt 事件,以显示自定义安装界面:
// Basic pattern
const [deferredPrompt, setDeferredPrompt] = useState(null);
useEffect(() => {
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
setDeferredPrompt(e);
});
}, []);
const handleInstall = async () => {
if (deferredPrompt) {
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
// outcome: 'accepted' or 'dismissed'
}
};
参见:
references/install-prompt.md,了解完整的usePWAInstallhook 和组件
离线体验
关键模式:
- 导航失败时回退到离线页面
- 使用
useOnlineStatushook 检测网络连接 - 显示离线横幅,告知用户当前状态
参见:
references/offline-handling.md,查看实现方式
后台同步
离线时将操作加入队列,在网络连接恢复后执行:
// In Service Worker
self.addEventListener('sync', (event) => {
if (event.tag === 'sync-data') {
event.waitUntil(syncPendingData());
}
});
// In App - trigger sync
const registration = await navigator.serviceWorker.ready;
await registration.sync.register('sync-data');
参见:
references/background-sync.md,了解完整的 IndexedDB 集成
更新流程
在有新版本可用时通知用户:
// Basic pattern
registration.addEventListener('updatefound', () => {
const newWorker = registration.installing;
newWorker?.addEventListener('statechange', () => {
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
// New version available - show update prompt
}
});
});
参见:
references/update-flow.md,了解usePWAUpdatehook 和更新策略
Next.js 集成
Next.js PWA 的选项:
- next-pwa - 适用于标准 Next.js 服务端
- 自定义 SW -
output: 'export'(静态网站)时必需 - Workbox CLI - 在构建后生成 SW
参见:
references/nextjs-integration.md,了解详细配置
快速参考
| 任务 | 解决方案 |
|---|---|
| 检查是否已安装 | window.matchMedia('(display-mode: standalone)').matches |
| 强制更新 SW | registration.update() |
| 清除所有缓存 | caches.keys().then(keys => keys.forEach(k => caches.delete(k))) |
| 检查网络状态 | navigator.onLine |
| 获取 SW 注册信息 | navigator.serviceWorker.ready |
| 跳过等待 | 在 SW 中调用 self.skipWaiting() |
| 接管控制权 | 在 SW 中调用 self.clients.claim() |
测试 PWA
Chrome DevTools
- Application 标签页 → Manifest、Service Workers、Cache Storage
- Lighthouse → PWA 审计
- Network → 勾选 Offline 复选框进行模拟
调试清单
- 清单已加载(应用 → 清单)
- SW 已注册(应用 → 服务工作线程)
- 缓存已填充(应用 → 缓存存储)
- 安装提示已触发(在控制台中检查 beforeinstallprompt)
- 离线页面可用(网络 → 离线)
- 更新流程可用(触发更新,验证提示)
参考资料
/references/ 中的详细实现:
service-worker-patterns.md- 缓存策略实现install-prompt.md-usePWAInstallhook 和安装组件offline-handling.md- 离线页面、状态 hook 和横幅background-sync.md- 使用 IndexedDB 的后台同步update-flow.md- 更新检测和用户提示nextjs-integration.md- Next.js PWA 配置选项
评论
支持 Markdown