nextjs-pwa について
Next.js でプログレッシブウェブアプリを実装する開発者向けガイドです。インストール対応、オフライン利用、キャッシュについて、標準機能と Serwist の設定、制約、移行時の要点を説明します。
主な機能
- 01標準機能と Serwist の比較
- 02ウェブアプリマニフェストの設定
- 03Service Worker の生成と登録
- 04キャッシュとオフライン戦略の利用
- 05Serwist のバージョン変更を確認
活用シーン
- 01Next.js アプリにインストール対応を追加
- 02オフラインキャッシュとフォールバックページを追加
- 03Pages Router プロジェクトの実装方法を選ぶ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ just-mpm/ conformai --skill nextjs-pwaインストール後、Claude Code で/nextjs-pwaを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/implementation-approaches.mdnative-nextjs-implementation.mdserwist-implementation.md詳細
Next.js PWA 実装ガイド(2025)
2025年時点で最も新しい手法を用いて、Next.js でプログレッシブウェブアプリ(PWA)を実装するための包括的なガイドです。
クイックスタートの判断ツリー
この判断ツリーに従って、適切な実装方法を選択してください。
Need PWA with Next.js?
│
├─ Basic installability only?
│ └─ Use: Native Next.js PWA Support
│ ✓ Zero dependencies
│ ✓ Built-in App Router support
│ ✓ Simple manifest.ts/json
│ ✗ No offline caching
│
└─ Need offline functionality?
└─ Use: Serwist Package
✓ Advanced caching strategies
✓ Service worker management
✓ Background sync
✓ Push notifications
⚠ Requires configuration
アプローチ 1:Next.js のネイティブ PWA サポート
概要
Next.js の組み込み機能を使った、依存関係ゼロの PWA 実装です。
使用するケース
- ✅ App Router(
/appディレクトリ)を使用している - ✅ 基本的な PWA 機能(インストール可能性、マニフェスト)が必要
- ✅ 複雑なオフラインキャッシュは必要ない
- ✅ 外部依存関係をゼロにしたい
- ✅ Next.js の公式推奨に従いたい
主な機能
- 2024年秋から組み込みでサポート(公式 PWA ガイドが公開)
- 外部パッケージは不要
manifest.ts、manifest.json、またはmanifest.webmanifestによるマニフェスト生成- App Router とシームレスに連携
MetadataRoute.Manifest型による TypeScript サポート
制限事項
- オフライン機能は自動ではサポートされない
- サービスワーカーは生成されない
- 高度なキャッシュ戦略はない
- オフライン機能にはサービスワーカーの手動実装が必要
クイック実装
1. マニフェストを作成(app/manifest.ts):
import type { MetadataRoute } from 'next'
export default function manifest(): MetadataRoute.Manifest {
return {
name: 'Your App Name',
short_name: 'App',
description: 'Your app description',
start_url: '/',
display: 'standalone',
background_color: '#ffffff',
theme_color: '#000000',
icons: [
{
src: '/icon-192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: '/icon-512.png',
sizes: '512x512',
type: 'image/png',
},
],
}
}
2. メタタグを追加(app/layout.tsx):
export const metadata = {
manifest: '/manifest.webmanifest',
appleWebApp: {
capable: true,
statusBarStyle: 'default',
title: 'Your App Name',
},
}
3. HTTPS でデプロイ(本番環境の PWA では必須)
アプローチ 2:Serwist パッケージ
概要
オフラインサポート、キャッシュ戦略、サービスワーカー管理を備えた高度な PWA 実装です。
使用するケース
- ✅ オフライン機能が必要
- ✅ 高度なキャッシュ戦略が必要
- ✅ バックグラウンド同期が必要
- ✅ プッシュ通知が必要
- ✅ 複雑なサービスワーカーのロジックが必要
- ✅ きめ細かなキャッシュ制御が必要
バージョン情報(2025年11月更新)
- Serwist 最新安定版: 9.2.1+
- プレビュー版: 10.0.0-preview(開発中)
- 破壊的変更: v9.0.0 で API に大幅な変更が導入(2024年3月)
- 必要な Node.js: 18.0.0+(22.x を推奨)
- TypeScript: 5.0.0+
主な機能
- サービスワーカーの自動生成
- 静的アセットの事前キャッシュ
- 実行時キャッシュ戦略(CacheFirst、NetworkFirst、StaleWhileRevalidate)
- バックグラウンド同期
- プッシュ通知のサポート
- オフライン時のフォールバックページ
- TypeScript サポート
Turbopack との互換性(2025年11月更新)
重要なお知らせ:
✅ 本番ビルド(next build):完全に互換性あり - Turbopack で通常どおり動作します
⚠️ 開発(next dev --turbo):警告が表示されますが、完全に機能します
開発時の警告への対処方法:
# Option 1: Suppress warning (Recommended for dev)
# Add to .env.local
SERWIST_SUPPRESS_TURBOPACK_WARNING="1"
# Option 2: Use webpack in development
npm run dev -- --webpack
注: 本番ビルドでは --webpack フラグは不要です。Serwist は本番環境で Turbopack とネイティブに連携します。
インストール
npm i @serwist/next && npm i -D serwist
# or
yarn add @serwist/next && yarn add -D serwist
# or
pnpm add @serwist/next && pnpm add -D serwist
クイック実装
1. next.config.js を設定:
import withSerwistInit from '@serwist/next'
const withSerwist = withSerwistInit({
swSrc: 'app/sw.ts',
swDest: 'public/sw.js',
cacheOnNavigation: true,
reloadOnOnline: true,
disable: process.env.NODE_ENV === 'development', // Optional
})
export default withSerwist({
// Your Next.js config
})
2. サービスワーカーを作成(app/sw.ts):
import { Serwist } from 'serwist'
const serwist = new Serwist({
precacheEntries: self.__SW_MANIFEST,
skipWaiting: true,
clientsClaim: true,
navigationPreload: true,
runtimeCaching: [
{
urlPattern: /^https:\/\/fonts\.(?:googleapis|gstatic)\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'google-fonts',
expiration: {
maxEntries: 4,
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 year
},
},
},
{
urlPattern: /\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'static-font-assets',
expiration: {
maxEntries: 4,
maxAgeSeconds: 7 * 24 * 60 * 60, // 1 week
},
},
},
{
urlPattern: /\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'static-image-assets',
expiration: {
maxEntries: 64,
maxAgeSeconds: 24 * 60 * 60, // 1 day
},
},
},
{
urlPattern: /\/_next\/image\?url=.+$/i,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'next-image',
expiration: {
maxEntries: 64,
maxAgeSeconds: 24 * 60 * 60, // 1 day
},
},
},
{
urlPattern: /\.(?:js)$/i,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'static-js-assets',
expiration: {
maxEntries: 32,
maxAgeSeconds: 24 * 60 * 60, // 1 day
},
},
},
{
urlPattern: /\.(?:css|less)$/i,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'static-style-assets',
expiration: {
maxEntries: 32,
maxAgeSeconds: 24 * 60 * 60, // 1 day
},
},
},
{
urlPattern: /\/_next\/data\/.+\/.+\.json$/i,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'next-data',
expiration: {
maxEntries: 32,
maxAgeSeconds: 24 * 60 * 60, // 1 day
},
},
},
{
urlPattern: /\/api\/.*/i,
handler: 'NetworkFirst',
method: 'GET',
options: {
cacheName: 'apis',
expiration: {
maxEntries: 16,
maxAgeSeconds: 24 * 60 * 60, // 1 day
},
networkTimeoutSeconds: 10,
},
},
{
urlPattern: /.*/i,
handler: 'NetworkFirst',
options: {
cacheName: 'others',
expiration: {
maxEntries: 32,
maxAgeSeconds: 24 * 60 * 60, // 1 day
},
networkTimeoutSeconds: 10,
},
},
],
})
serwist.addEventListeners()
3. サービスワーカーを登録(app/layout.tsx):
'use client'
import { useEffect } from 'react'
export default function RootLayout({ children }) {
useEffect(() => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/sw.js')
.then((registration) => {
console.log('Service Worker registered:', registration)
})
.catch((error) => {
console.error('Service Worker registration failed:', error)
})
}
}, [])
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
4. tsconfig.json を更新:
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext", "webworker"],
"types": ["@serwist/next/typings"]
}
}
5. マニフェストを作成(ネイティブアプローチと同じ)
破壊的変更:Serwist v9.0.0+
古いバージョンから移行する場合は、次の重要な変更に注意してください。
1. インポートの変更
// ❌ OLD (v8.x and earlier)
import { installSerwist } from '@serwist/sw'
// ✅ NEW (v9.0.0+)
import { Serwist } from 'serwist'
2. 初期化方法の変更
// ❌ OLD
const sw = installSerwist({ /* config */ })
// ✅ NEW
const serwist = new Serwist({ /* config */ })
serwist.addEventListeners() // Required!
3. パッケージの統合
# ❌ OLD
npm i @serwist/precaching @serwist/routing @serwist/strategies
# ✅ NEW (all in one)
npm i -D serwist
比較:ネイティブと Serwist
| 機能 | Next.js ネイティブ | Serwist |
|---|---|---|
| セットアップの複雑さ | ⭐ シンプル | ⭐⭐⭐ 中程度 |
| 依存関係 | ✅ ゼロ | ⚠️ 2 パッケージ |
| オフラインサポート | ❌ 手動 | ✅ 自動 |
| キャッシュ戦略 | ❌ なし | ✅ 複数 |
| サービスワーカー | ❌ 手動 | ✅ 自動生成 |
| App Router サポート | ✅ ネイティブ | ✅ 完全 |
| Pages Router サポート | ⚠️ 限定的 | ✅ 完全 |
| TypeScript | ✅ 組み込み | ✅ 完全 |
| 本番環境対応 | ✅ はい | ✅ はい |
| Turbopack との互換性 | ✅ はい | ✅ はい(環境変数が必要) |
よくある問題と解決策
問題 1:サービスワーカーが更新されない
解決策: サービスワーカーにバージョンを設定するか、skipWaiting: true を使用してください
問題 2:キャッシュされたコンテンツが更新されない
解決策: 適切なキャッシュ無効化戦略を実装するか、maxAgeSeconds を小さくしてください
問題 3:開発環境での Turbopack 警告
解決策: .env.local に SERWIST_SUPPRESS_TURBOPACK_WARNING="1" を追加してください
問題 4:HTTPS が必要というエラー
解決策: HTTPS ドメインにデプロイしてください(テストには localhost を使用できます)
問題 5:アイコンが表示されない
解決策: アイコンが public/ ディレクトリにあり、マニフェストのパスが正しいことを確認してください
推奨事項
新規プロジェクトの場合:
- Next.js 標準の PWA から始める(シンプルで、依存関係がありません)
- オフライン機能が必要になった場合にのみ Serwist にアップグレードする
既存のプロジェクトの場合:
next-pwaから移行しますか? → Serwist を使用してください(直接置き換えられます)- すでにカスタムサービスワーカーを使用していますか? → そのまま使用するか、Serwist にリファクタリングしてください
- Pages Router を使用していますか? → Serwist を推奨します(より優れたサポート)
本番環境の場合:
- ✅ 常に HTTPS を使用してください
- ✅ オフライン機能を十分にテストしてください
- ✅ 適切なエラー処理を実装してください
- ✅ サービスワーカーの更新を監視してください
- ✅ アセットごとに適切なキャッシュ戦略を使用してください
リソース
- Next.js PWA ドキュメント: https://nextjs.org/docs/app/api-reference/file-conventions/metadata/manifest
- Serwist ドキュメント: https://serwist.pages.dev
- Serwist GitHub: https://github.com/serwist/serwist
- Web App Manifest 仕様: https://www.w3.org/TR/appmanifest/
- Service Worker API: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
バージョン履歴
- 2025年11月: Serwist のバージョン情報を更新し、Turbopack との互換性に関する説明を明確化
- 2024年秋: Next.js 標準の PWA サポートが公式にドキュメント化
- 2024年3月: Serwist v9.0.0 を破壊的変更とともにリリース
- 2023年: Workbox の最新の代替として Serwist を作成
完全かつ最新の情報については、以下のファイルを参照してください:
C:\Users\tetu_.claude\skills\nextjs-pwa\references\serwist-implementation.md C:\Users\tetu_.claude\skills\nextjs-pwa\references\native-nextjs-implementation.md C:\Users\tetu_.claude\skills\nextjs-pwa\references\implementation-approaches.md
最終更新日: 2025年11月13日