Como Desenvolver uma PWA (Progressive Web App) com Claude Code
Aprenda a develop a pwa (progressive web app) usando o Claude Code. Inclui exemplos praticos de codigo e orientacao passo a passo.
PWAとは
PWA(Progressive Web App)はWebの技術でネイティブアプリに近い体験を提供するアプローチです。Claude Codeを使えば、Service Workerやマニフェストの設定を効率的に実装できます。基本的な使い方はClaude Code入門ガイドを参照してください。
Web App Manifest
{
"name": "My PWA Application",
"short_name": "MyPWA",
"description": "高速で信頼性の高いWebアプリケーション",
"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"
}
]
}
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();
});
キャッシュ戦略
// Stale While Revalidate 戦略
self.addEventListener("fetch", (event: FetchEvent) => {
const { request } = event;
const url = new URL(request.url);
// API リクエスト: 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;
}
// HTMLページ: 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;
}
オフラインページ
// オフライン検出コンポーネント
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>
);
}
Service Worker の登録
// Service Worker登録
async function registerServiceWorker() {
if (!("serviceWorker" in navigator)) {
console.log("Service Worker not supported");
return;
}
try {
const registration = await navigator.serviceWorker.register(
"/sw.js",
{ scope: "/" }
);
// 更新チェック
registration.addEventListener("updatefound", () => {
const newWorker = registration.installing;
newWorker?.addEventListener("statechange", () => {
if (
newWorker.state === "installed" &&
navigator.serviceWorker.controller
) {
// 新しいバージョンが利用可能
showUpdateNotification();
}
});
});
console.log("Service Worker registered:", registration.scope);
} catch (error) {
console.error("Registration failed:", error);
}
}
Claude Codeでの実装プロンプト
PWA開発をClaude Codeに依頼する例です。パフォーマンスについてはコード分割・遅延読み込みも合わせて参照してください。
既存のReactアプリをPWA化して。
- Web App Manifestの作成
- Service Workerでオフライン対応
- 静的アセットはCache First、APIはNetwork First
- アプリ更新通知の実装
- Lighthouse PWAスコア100点を目指して
PWAの詳細はweb.dev PWAガイドを参照してください。Claude Codeの最新情報は公式ドキュメントで確認できます。
Summary
PWAはWebとネイティブの良いところ取りができる技術です。Claude Codeを使えば、Service Workerのキャッシュ戦略からオフライン対応まで、一貫したPWA実装を効率的に進められます。
PDF gratuito: Cheatsheet do Claude Code em 5 minutos
Basta informar seu e-mail e enviamos na hora o cheatsheet em uma página A4.
Cuidamos dos seus dados pessoais e nunca enviamos spam.
Sobre o autor
Masa
Engenheiro apaixonado por Claude Code. Mantém o claudecode-lab.com, uma mídia tech em 10 idiomas com mais de 2.000 páginas.
Artigos relacionados
7 verificações antes de publicar todos os dias um artigo multilíngue sobre Claude Code
Uma checklist prática para publicar artigos multilíngues sobre Claude Code todos os dias sem esquecer idiomas, quebrar CTAs ou deixar páginas antigas no ar.
O que e Codex Automations? Conteudo, analise e deploy com IA enquanto voce dorme
Guia pratico para usar Codex Automations em analytics, artigos, CTA, deploy e monetizacao.
Desenhe Firestore com Claude Code: comece pelas consultas
Workflow prático para Firestore com Claude Code: schema orientado por consultas, índices, custos, regras de segurança e TypeScript.