Use Cases

Cara Develop a PWA (Progressive Web App) dengan Claude Code

Pelajari cara develop a pwa (progressive web app) menggunakan Claude Code. Dilengkapi contoh kode praktis dan panduan langkah demi langkah.

PWA

Untuk PWA(Progressive Web App)はWebの技術でネイティブaplikasiに近い体験をpenyediaanするアプローチです。Claude Codeを使えば、Service Workerやマニフェストのpengaturanをefisienにimplementasiできます。dasar的な使い方, lihat Claude Code入門ガイド.

Web App Manifest

{
  "name": "My PWA Application",
  "short_name": "MyPWA",
  "description": "cepat reliabilitas 高いWebaplikasi",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#3b82f6",
  "orientation": "portrait-primary",
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-maskable-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ]
}

implementasi Service Worker

// sw.ts
const CACHE_NAME = "app-cache-v1";
const STATIC_ASSETS = [
  "/",
  "/offline.html",
  "/styles/main.css",
  "/scripts/app.js",
  "/icons/icon-192.png",
];

// Cache static assets on install
self.addEventListener("install", (event: ExtendableEvent) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      return cache.addAll(STATIC_ASSETS);
    })
  );
  // Activate immediately
  (self as any).skipWaiting();
});

// Delete old caches
self.addEventListener("activate", (event: ExtendableEvent) => {
  event.waitUntil(
    caches.keys().then((keys) => {
      return Promise.all(
        keys
          .filter((key) => key !== CACHE_NAME)
          .map((key) => caches.delete(key))
      );
    })
  );
  (self as any).clients.claim();
});

cache戦略

// Stale While Revalidate 戦略
self.addEventListener("fetch", (event: FetchEvent) => {
  const { request } = event;
  const url = new URL(request.url);

  // API request: Network First
  if (url.pathname.startsWith("/api/")) {
    event.respondWith(networkFirst(request));
    return;
  }

  // 静的アセット: Cache First
  if (request.destination === "image" || url.pathname.match(/\.(css|js)$/)) {
    event.respondWith(cacheFirst(request));
    return;
  }

  // HTMLhalaman: Stale While Revalidate
  event.respondWith(staleWhileRevalidate(request));
});

async function networkFirst(request: Request): Promise<Response> {
  try {
    const response = await fetch(request);
    const cache = await caches.open(CACHE_NAME);
    cache.put(request, response.clone());
    return response;
  } catch {
    const cached = await caches.match(request);
    return cached || new Response('{"error": "offline"}', {
      status: 503,
      headers: { "Content-Type": "application/json" },
    });
  }
}

async function cacheFirst(request: Request): Promise<Response> {
  const cached = await caches.match(request);
  if (cached) return cached;

  const response = await fetch(request);
  const cache = await caches.open(CACHE_NAME);
  cache.put(request, response.clone());
  return response;
}

async function staleWhileRevalidate(
  request: Request
): Promise<Response> {
  const cache = await caches.open(CACHE_NAME);
  const cached = await cache.match(request);

  const fetchPromise = fetch(request).then((response) => {
    cache.put(request, response.clone());
    return response;
  });

  return cached || fetchPromise;
}

Halaman Offline

// オフライン検出komponen
import { useState, useEffect } from "react";

function useOnlineStatus() {
  const [isOnline, setIsOnline] = useState(navigator.onLine);

  useEffect(() => {
    const handleOnline = () => setIsOnline(true);
    const handleOffline = () => setIsOnline(false);

    window.addEventListener("online", handleOnline);
    window.addEventListener("offline", handleOffline);

    return () => {
      window.removeEventListener("online", handleOnline);
      window.removeEventListener("offline", handleOffline);
    };
  }, []);

  return isOnline;
}

function OfflineBanner() {
  const isOnline = useOnlineStatus();

  if (isOnline) return null;

  return (
    <div className="bg-yellow-500 text-white text-center p-2">
      オフラインです。一部の機能が制限されています。
    </div>
  );
}

registrasi Service Worker

// Service Workerregistrasi
async function registerServiceWorker() {
  if (!("serviceWorker" in navigator)) {
    console.log("Service Worker not supported");
    return;
  }

  try {
    const registration = await navigator.serviceWorker.register(
      "/sw.js",
      { scope: "/" }
    );

    // pembaruanチェック
    registration.addEventListener("updatefound", () => {
      const newWorker = registration.installing;
      newWorker?.addEventListener("statechange", () => {
        if (
          newWorker.state === "installed" &&
          navigator.serviceWorker.controller
        ) {
          // 新しいversi pemanfaatandimungkinkan
          showUpdateNotification();
        }
      });
    });

    console.log("Service Worker registered:", registration.scope);
  } catch (error) {
    console.error("Registration failed:", error);
  }
}

Prompt Implementasi dengan Claude Code

PWApengembangan Claude Code 依頼 例.performa mengenai コード分割・遅延loading juga 合わせて参照 .

既存 Reactaplikasi PWA化して。
- Web App Manifest pembuatan
- Service Worker dengan オフラインdukungan
- 静的アセット Cache First、API Network First
- aplikasipembaruannotifikasi implementasi
- Lighthouse PWAスコア100点 目指して

PWA 詳細 web.dev PWApanduan silakan lihat.Claude Code 最新情報 公式dokumen konfirmasi bisa dilakukan.

Summary

PWA Web dan ネイティブ 良い dan ころ取り きる技術.Claude Code 使えば、Service Worker cache戦略 dari オフラインdukunganま 、一貫 PWAimplementasi efisien 進められ.

#Claude Code #PWA #Service Worker #offline #mobile