mcpField
P
pwa-expert

pwa-expert

github.com/curiositech開発257546 回インストール2 日前に更新
リポジトリ

pwa-expert について

インストール可能でオフライン対応のプログレッシブウェブアプリを構築する開発スキルです。マニフェスト、Service Workerのキャッシュ、インストールプロンプト、バックグラウンド同期、更新フローに加え、Next.jsの選択肢も扱います。

主な機能

  1. 01Web App Manifestの設定
  2. 02Service Workerの登録とキャッシュ
  3. 03インストールプロンプトの処理
  4. 04オフライン時の代替表示と状態管理
  5. 05バックグラウンド同期と更新フロー
  6. 06Next.js向けPWAの選択肢

活用シーン

  1. 01Webアプリをインストール可能にする
  2. 02オフライン利用向けにアセットをキャッシュ
  3. 03接続回復まで操作を保留
  4. 04アプリの更新をユーザーに通知

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/curiositech/some_claude_skills --skill pwa-expert

インストール後、Claude Code で/pwa-expertを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

.claude-plugin/
plugin.json
references/
nextjs-integration.md
service-worker-patterns.md
background-sync.md
install-prompt.md
update-flow.md
offline-handling.md

詳細

プログレッシブウェブアプリのエキスパート

Service Worker、スマートキャッシュ、ネイティブアプリのような操作感で、インストール可能なオフライン対応ウェブアプリを構築します。

このスキルを使う場面

  • モバイル/デスクトップでウェブアプリをインストール可能にする
  • オフライン機能を実装する
  • Service Worker のキャッシュ戦略を設定する
  • インストールプロンプト(beforeinstallprompt)を処理する
  • オフラインファーストのアプリにバックグラウンド同期を実装する
  • PWA の更新フローを管理する
  • ウェブアプリマニフェストを作成する

このスキルを使わない場面

  • ネイティブアプリの開発 → React Native、Flutter、またはネイティブ SDK を使用してください
  • 一般的なウェブパフォーマンス → Lighthouse/パフォーマンス監査ツールを使用してください
  • サーバーサイドレンダリングの問題 → Next.js/フレームワーク固有のドキュメントを参照してください
  • プッシュ通知のみ → 専用のプッシュ通知サービスを検討してください
  • シンプルな静的サイト → PWA のオーバーヘッドに見合わない場合があります

基本概念

PWA をインストール可能にする要件
  1. HTTPS(または開発時の localhost)
  2. 必須フィールドを含む ウェブアプリマニフェスト
  3. fetch ハンドラーを備えた Service Worker
  4. アイコン(最低 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)    │
└─────────────────────────────────────────┘

ウェブアプリマニフェスト

完全な 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ブラウザー UI を表示せず、全画面で表示します
standaloneURL バーのないアプリのような表示です(推奨)
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-FirstAPI データ、ユーザーコンテンツ遅くなり、接続が必要です
Stale-While-Revalidate最新性と速度のバランスバックグラウンドで更新します
Network-Only認証、リアルタイムデータオフラインでは利用できません
Cache-Onlyバージョン管理されたアセット更新されません

参照: 完全な実装については references/service-worker-patterns.md を参照してください

インストールプロンプト

beforeinstallprompt イベントを処理して、カスタムのインストール UI を表示します。

// 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'
  }
};

参照: usePWAInstall フックとコンポーネントの完全な実装については references/install-prompt.md を参照してください

オフラインでの操作体験

主なパターン:

  • ナビゲーションに失敗した場合のオフラインページへのフォールバック
  • 接続状態を検出する useOnlineStatus フック
  • ユーザーに知らせるオフラインバナー

参照: 実装については 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');

参照: IndexedDB との完全な統合については references/background-sync.md を参照してください

更新フロー

新しいバージョンが利用可能になったことをユーザーに通知します。

// 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
    }
  });
});

参照: usePWAUpdate フックと更新戦略については references/update-flow.md を参照してください

Next.js との統合

Next.js で PWA を実現する方法:

  1. next-pwa - 標準の Next.js サーバーで動作します
  2. カスタム SW - output: 'export'(静的サイト)で必要です
  3. 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
  1. Application タブ → Manifest、Service Workers、Cache Storage
  2. Lighthouse → PWA 監査
  3. Network → Offline チェックボックスでシミュレーション
デバッグチェックリスト
  • マニフェストが読み込まれる(Application → Manifest)
  • SW が登録される(Application → Service Workers)
  • キャッシュにデータが格納される(Application → Cache Storage)
  • インストールプロンプトが表示される(beforeinstallprompt を Console で確認)
  • オフラインページが動作する(Network → Offline)
  • 更新フローが動作する(更新を実行し、プロンプトを確認)

参考資料

詳細な実装については /references/ を参照してください。

  • service-worker-patterns.md - キャッシュ戦略の実装
  • install-prompt.md - usePWAInstall フックとインストールコンポーネント
  • offline-handling.md - オフラインページ、ステータスフック、バナー
  • background-sync.md - IndexedDB を使ったバックグラウンド同期
  • update-flow.md - 更新の検出とユーザープロンプト
  • nextjs-integration.md - Next.js の PWA 設定オプション

コメント