nextjs について
Next.js App Routerを使う開発者向けのスキルです。Next.js 16とReact 19.2の実践パターンを、破壊的変更、キャッシュAPI、移行、エラー対応を中心に解説します。
主な機能
- 01Next.js 16への移行ガイド
- 02非同期ルートパラメーターの処理
- 03Cache ComponentsとキャッシュAPI
- 04Proxyと並列ルートの設定
- 05一般的なエラーと解決策
活用シーン
- 01Next.js 15から16へのプロジェクト移行
- 02App Routerのキャッシュ設定
- 03並列ルートや非同期パラメーターの問題解決
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ovachiever/ droid-tings --skill nextjsインストール後、Claude Code で/nextjsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.md.claude-plugin/plugin.jsonreferences/next-16-migration-guide.mdtop-errors.mdscripts/check-versions.shtemplates/app-router-async-params.tsxcache-component-use-cache.tsxpackage.jsonparallel-routes-with-default.tsxproxy-migration.tsroute-handler-api.tsserver-actions-form.tsx詳細
Next.js App Router - 本番環境向けパターン
バージョン: Next.js 16.0.0 React バージョン: 19.2.0 Node.js: 20.9+ 最終検証日: 2025-10-24
目次
- このスキルを使用する場面
- このスキルを使用しない場面
- Next.js 16 の破壊的変更
- Cache Components とキャッシュ API
- Route Handlers(Next.js 16 の更新)
- Proxy と Middleware
- Parallel Routes - default.js が必須
- React 19.2 の機能
- Turbopack(Next.js 16 で安定版)
- よくあるエラーと解決策
- テンプレートとリソース
このスキルを使用する場面
焦点:Next.js 16 の破壊的変更と知識の不足を補うこと(2024 年 12 月以降)。
次のような場合にこのスキルを使用してください。
- Next.js 16 の破壊的変更(非同期の params、proxy.ts、parallel routes の default.js、削除された機能)
"use cache"ディレクティブを使用する Cache Components(Next.js 16 の新機能)- 新しいキャッシュ API:
revalidateTag()、updateTag()、refresh()(Next.js 16 で更新) - Next.js 15 から 16 への移行(破壊的変更によるエラーを回避)
- 非同期のルートパラメーター(
params、searchParams、cookies()、headers()が非同期に変更) - default.js を使用する Parallel Routes(Next.js 16 で必須)
- React 19.2 の機能(View Transitions、
useEffectEvent()、React Compiler) - Turbopack(Next.js 16 で安定版となり、デフォルトで有効)
- 画像のデフォルト設定の変更(Next.js 16 の TTL、サイズ、品質)
- エラーの予防(解決策とともに記載された 18 件以上の Next.js 16 のエラー)
このスキルを使用しない場面
次の用途にはこのスキルを使用しないでください。
- Cloudflare Workers へのデプロイ → 代わりに
cloudflare-nextjsスキルを使用してください - Pages Router のパターン → このスキルの対象は App Router のみです(Pages Router はレガシーです)
- 認証ライブラリ →
clerk-auth、better-auth、または認証に特化した別のスキルを使用してください - データベース連携 →
cloudflare-d1、drizzle-orm-d1、またはデータベースに特化した別のスキルを使用してください - UI コンポーネントライブラリ → Tailwind と shadcn/ui には
tailwind-v4-shadcnスキルを使用してください - 状態管理 →
zustand-state-management、tanstack-queryスキルを使用してください - フォームライブラリ →
react-hook-form-zodスキルを使用してください - Vercel 固有の機能 → Vercel プラットフォームのドキュメントを参照してください
- Next.js Enterprise の機能(ISR、DPR)→ Next.js Enterprise のドキュメントを参照してください
- デプロイ設定 → プラットフォームに特化したデプロイ用スキルを使用してください
他のスキルとの関係:
- cloudflare-nextjs:Next.js を Cloudflare Workers にデプロイする場合に使用します(Cloudflare にデプロイする場合は、両方のスキルを併用してください)
- tailwind-v4-shadcn:Tailwind v4 と shadcn/ui のセットアップに使用します(このスキルと組み合わせて使用できます)
- clerk-auth:Next.js での Clerk 認証に使用します(このスキルと組み合わせて使用できます)
- better-auth:Better Auth の連携に使用します(このスキルと組み合わせて使用できます)
Next.js 16 の破壊的変更
重要:Next.js 16 では複数の破壊的変更が導入されています。Next.js 15 以前から移行する場合は、このセクションを注意深く読んでください。
1. 非同期のルートパラメーター(破壊的変更)
破壊的変更:params、searchParams、cookies()、headers()、draftMode() は非同期になり、await が必要です。
変更前(Next.js 15):
// ❌ This no longer works in Next.js 16
export default function Page({ params, searchParams }: {
params: { slug: string }
searchParams: { query: string }
}) {
const slug = params.slug // ❌ Error: params is a Promise
const query = searchParams.query // ❌ Error: searchParams is a Promise
return <div>{slug}</div>
}
変更後(Next.js 16):
// ✅ Correct: await params and searchParams
export default async function Page({ params, searchParams }: {
params: Promise<{ slug: string }>
searchParams: Promise<{ query: string }>
}) {
const { slug } = await params // ✅ Await the promise
const { query } = await searchParams // ✅ Await the promise
return <div>{slug}</div>
}
対象:
- ページ、レイアウト、ルートハンドラーの
params - ページの
searchParams next/headersのcookies()next/headersのheaders()next/headersのdraftMode()
移行:
// ❌ Before
import { cookies, headers } from 'next/headers'
export function MyComponent() {
const cookieStore = cookies() // ❌ Sync access
const headersList = headers() // ❌ Sync access
}
// ✅ After
import { cookies, headers } from 'next/headers'
export async function MyComponent() {
const cookieStore = await cookies() // ✅ Async access
const headersList = await headers() // ✅ Async access
}
Codemod:npx @next/codemod@canary upgrade latest を実行すると、自動的に移行できます。
テンプレートを参照:templates/app-router-async-params.tsx
2. Middleware から Proxy への移行(破壊的変更)
破壊的変更:Next.js 16 では middleware.ts は非推奨です。代わりに proxy.ts を使用してください。
変更の理由:proxy.ts は Node.js ランタイム(Edge ランタイムではなく)で実行され、ネットワーク境界を明確にします。これにより、エッジミドルウェアとサーバーサイドプロキシの違いがより明確になります。
移行手順:
- ファイル名を変更:
middleware.ts→proxy.ts - 関数名を変更:
middleware→proxy - 設定を更新:
matcher→config.matcher(構文は同じ)
変更前(Next.js 15):
// middleware.ts ❌ Deprecated in Next.js 16
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const response = NextResponse.next()
response.headers.set('x-custom-header', 'value')
return response
}
export const config = {
matcher: '/api/:path*',
}
変更後(Next.js 16):
// proxy.ts ✅ New in Next.js 16
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function proxy(request: NextRequest) {
const response = NextResponse.next()
response.headers.set('x-custom-header', 'value')
return response
}
export const config = {
matcher: '/api/:path*',
}
注:Next.js 16 でも middleware.ts は引き続き動作しますが、非推奨です。今後の互換性のために proxy.ts に移行してください。
テンプレートを参照:templates/proxy-migration.ts
リファレンスを参照:references/proxy-vs-middleware.md
3. Parallel Routes で default.js が必須に(破壊的変更)
破壊的変更:Parallel Routes では、明示的な default.js ファイルが必須になりました。ファイルがない場合、ソフトナビゲーション時にルートが失敗します。
構成:
app/
├── @auth/
│ ├── login/
│ │ └── page.tsx
│ └── default.tsx ← REQUIRED in Next.js 16
├── @dashboard/
│ ├── overview/
│ │ └── page.tsx
│ └── default.tsx ← REQUIRED in Next.js 16
└── layout.tsx
レイアウト:
// app/layout.tsx
export default function Layout({
children,
auth,
dashboard,
}: {
children: React.ReactNode
auth: React.ReactNode
dashboard: React.ReactNode
}) {
return (
<html>
<body>
{auth}
{dashboard}
{children}
</body>
</html>
)
}
デフォルトフォールバック(必須):
// app/@auth/default.tsx
export default function AuthDefault() {
return null // or <Skeleton /> or redirect
}
// app/@dashboard/default.tsx
export default function DashboardDefault() {
return null
}
必須である理由:Next.js 16 では、Parallel Routes によるソフトナビゲーションの処理方法が変更されました。default.js がない場合、クライアントサイドナビゲーション時に一致しないスロットでエラーが発生します。
テンプレートを参照:templates/parallel-routes-with-default.tsx
4. 削除された機能(破壊的変更)
以下の機能は Next.js 16 で削除されました:
- AMP サポート - 完全に削除されました。標準ページに移行してください。
next lintコマンド - ESLint または Biome を直接使用してください。serverRuntimeConfigとpublicRuntimeConfig- 代わりに環境変数を使用してください。experimental.pprフラグ - Cache Components に進化しました。"use cache"ディレクティブを使用してください。- 自動的な
scroll-behavior: smooth- 必要に応じて手動で追加してください。 - Node.js 18 のサポート - 最低バージョンは 20.9+ になりました。
移行方法:
- AMP:AMP ページを標準ページに変換するか、別の AMP 実装を使用します。
- Lint:
npx eslint .またはnpx biome lint .を直接実行します。 - 設定:
serverRuntimeConfigをprocess.env.VARIABLEに置き換えます。 - PPR:
experimental.pprから"use cache"ディレクティブに移行します(Cache Components のセクションを参照)。
5. バージョン要件(破壊的変更)
Next.js 16 の要件:
- Node.js:20.9+(Node.js 18 はサポート対象外になりました)
- TypeScript:5.1+(TypeScript を使用する場合)
- React:19.2+(Next.js 16 とともに自動的にインストールされます)
- ブラウザー:Chrome 111+、Safari 16.4+、Firefox 109+、Edge 111+
バージョンを確認:
node --version # Should be 20.9+
npm --version # Should be 10+
npx next --version # Should be 16.0.0+
Node.js をアップグレード:
# Using nvm
nvm install 20
nvm use 20
nvm alias default 20
# Using Homebrew (macOS)
brew install node@20
# Using apt (Ubuntu/Debian)
sudo apt update
sudo apt install nodejs npm
6. 画像のデフォルト設定が変更(破壊的変更)
Next.js 16 では next/image のデフォルト設定が変更されました:
| 設定 | Next.js 15 | Next.js 16 |
|---|---|---|
| TTL(キャッシュ期間) | 60 秒 | 4 時間 |
| imageSizes | [16, 32, 48, 64, 96, 128, 256, 384] | [640, 750, 828, 1080, 1200](削減) |
| qualities | [75, 90, 100] | [75](単一の品質) |
影響:
- 画像のキャッシュ期間が長くなります(60 秒から 4 時間に延長)。
- 生成される画像サイズが少なくなります(ビルドサイズは小さくなりますが、サイズの粒度は低下します)。
- 複数の品質ではなく、単一の品質(75)で生成されます。
デフォルト設定を上書き(必要な場合):
// next.config.ts
import type { NextConfig } from 'next'
const config: NextConfig = {
images: {
minimumCacheTTL: 60, // Revert to 60 seconds
deviceSizes: [640, 750, 828, 1080, 1200, 1920], // Add larger sizes
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], // Restore old sizes
formats: ['image/webp'], // Default
},
}
export default config
テンプレートを参照:templates/image-optimization.tsx
Cache Components とキャッシュ API
Next.js 16 の新機能:Cache Components は "use cache" ディレクティブによるオプトイン方式のキャッシュを導入し、Next.js 15 の暗黙的なキャッシュに置き換わります。
1. 概要
変更点:
- Next.js 15:暗黙的なキャッシュ(すべての Server Component がデフォルトでキャッシュされます)
- Next.js 16:オプトイン方式のキャッシュ(
"use cache"ディレクティブを使用します)
変更の理由:明示的なキャッシュにより、開発者はより細かく制御でき、キャッシュの動作も予測しやすくなります。
Cache Components でできること:
- コンポーネント単位のキャッシュ(ページ全体ではなく、特定のコンポーネントをキャッシュします)
- 関数単位のキャッシュ(コストの高い計算をキャッシュします)
- ページ単位のキャッシュ(ページ全体を選択的にキャッシュします)
- Partial Prerendering(PPR) - 静的な部分をキャッシュし、動的な部分をオンデマンドでレンダリングします
2. "use cache" ディレクティブ
構文:Server Component、関数、またはルートハンドラーの先頭に "use cache" を追加します。
コンポーネント単位のキャッシュ:
// app/components/expensive-component.tsx
'use cache'
export async function ExpensiveComponent() {
const data = await fetch('https://api.example.com/data')
const json = await data.json()
return (
<div>
<h1>{json.title}</h1>
<p>{json.description}</p>
</div>
)
}
関数単位のキャッシュ:
// lib/data.ts
'use cache'
export async function getExpensiveData(id: string) {
const response = await fetch(`https://api.example.com/items/${id}`)
return response.json()
}
// Usage in component
import { getExpensiveData } from '@/lib/data'
export async function ProductPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
const product = await getExpensiveData(id) // Cached
return <div>{product.name}</div>
}
ページ単位のキャッシュ:
// app/blog/[slug]/page.tsx
'use cache'
export async function generateStaticParams() {
const posts = await fetch('https://api.example.com/posts').then(r => r.json())
return posts.map((post: { slug: string }) => ({ slug: post.slug }))
}
export default async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params
const post = await fetch(`https://api.example.com/posts/${slug}`).then(r => r.json())
return (
<article>
<h1>{post.title}</h1>
<div>{post.content}</div>
</article>
)
}
テンプレート:templates/cache-component-use-cache.tsx を参照してください。
3. Partial Prerendering(PPR)
PPR を使用すると、ページの静的な部分をキャッシュしながら、動的な部分をオンデマンドでレンダリングできます。
パターン:
// app/dashboard/page.tsx
// Static header (cached)
'use cache'
async function StaticHeader() {
return <header>My App</header>
}
// Dynamic user info (not cached)
async function DynamicUserInfo() {
const cookieStore = await cookies()
const userId = cookieStore.get('userId')?.value
const user = await fetch(`/api/users/${userId}`).then(r => r.json())
return <div>Welcome, {user.name}</div>
}
// Page combines both
export default function Dashboard() {
return (
<div>
<StaticHeader /> {/* Cached */}
<DynamicUserInfo /> {/* Dynamic */}
</div>
)
}
PPR を使用する場面:
- ページに静的コンテンツと動的コンテンツの両方がある場合
- レイアウト/ヘッダー/フッターをキャッシュしつつ、ユーザーごとのコンテンツをレンダリングしたい場合
- 高速な初期読み込み(静的部分)とパーソナライズ(動的部分)が必要な場合
リファレンス:references/cache-components-guide.md を参照してください。
4. revalidateTag() - 更新された API
破壊的変更:revalidateTag() で stale-while-revalidate の動作を実現するには、第 2 引数(cacheLife プロファイル)が必須になりました。
変更前(Next.js 15):
import { revalidateTag } from 'next/cache'
export async function updatePost(id: string) {
await fetch(`/api/posts/${id}`, { method: 'PATCH' })
revalidateTag('posts') // ❌ Only one argument in Next.js 15
}
変更後(Next.js 16):
import { revalidateTag } from 'next/cache'
export async function updatePost(id: string) {
await fetch(`/api/posts/${id}`, { method: 'PATCH' })
revalidateTag('posts', 'max') // ✅ Second argument required in Next.js 16
}
組み込みの Cache Life プロファイル:
'max'- 最大の古さを許容します(ほとんどのユースケースで推奨)'hours'- 数時間後に古くなります'days'- 数日後に古くなります'weeks'- 数週間後に古くなります'default'- デフォルトのキャッシュ動作
カスタム Cache Life プロファイル:
revalidateTag('posts', {
stale: 3600, // Stale after 1 hour (seconds)
revalidate: 86400, // Revalidate every 24 hours (seconds)
expire: false, // Never expire (optional)
})
Server Action でのパターン:
'use server'
import { revalidateTag } from 'next/cache'
export async function createPost(formData: FormData) {
const title = formData.get('title') as string
const content = formData.get('content') as string
await fetch('/api/posts', {
method: 'POST',
body: JSON.stringify({ title, content }),
})
revalidateTag('posts', 'max') // ✅ Revalidate with max staleness
}
テンプレート:templates/revalidate-tag-cache-life.ts を参照してください。
5. updateTag() - 新しい API(Server Action 専用)
Next.js 16 の新機能:updateTag() は Server Action で read-your-writes セマンティクスを提供します。
動作:
- キャッシュをただちに期限切れにします
- 同じリクエスト内でデータを更新します
- ミューテーション直後に更新されたデータを表示します(古いデータは表示されません)
revalidateTag() との違い:
revalidateTag():stale-while-revalidate(古いデータを表示し、バックグラウンドで再検証します)updateTag():即時更新(キャッシュを期限切れにし、同じリクエスト内で最新のデータを取得します)
ユースケース:フォーム、ユーザー設定など、ユーザーが即時のフィードバックを期待するあらゆるミューテーション。
パターン:
'use server'
import { updateTag } from 'next/cache'
export async function updateUserProfile(formData: FormData) {
const name = formData.get('name') as string
const email = formData.get('email') as string
// Update database
await db.users.update({ name, email })
// Immediately refresh cache (read-your-writes)
updateTag('user-profile')
// User sees updated data immediately (no stale data)
}
使い分け:
updateTag():ユーザー設定、プロフィールの更新、重要なミューテーション(即時のフィードバック)revalidateTag():ブログ記事、商品一覧、重要度の低い更新(バックグラウンドで再検証)
テンプレート:templates/server-action-update-tag.ts を参照してください。
6. refresh() - 新しい API(Server Action 専用)
Next.js 16 の新機能:refresh() はキャッシュされていないデータのみを更新します(クライアント側の router.refresh() を補完します)。
使用する場面:
- キャッシュされたデータに影響を与えずに、動的なデータを更新する場合
- サーバー側で
router.refresh()を補完する場合
パターン:
'use server'
import { refresh } from 'next/cache'
export async function refreshDashboard() {
// Refresh uncached data (e.g., real-time metrics)
refresh()
// Cached data (e.g., static header) remains cached
}
revalidateTag() および updateTag() との違い:
refresh():キャッシュされていないデータのみを更新しますrevalidateTag():特定のタグが付いたデータを再検証します(stale-while-revalidate)updateTag():特定のタグが付いたデータをただちに期限切れにし、更新します
リファレンス:references/cache-components-guide.md を参照してください。
Route Handler(Next.js 16 の更新)
Route Handler の非同期 Params(破壊的変更)
重要:Next.js 16 の Route Handler では、params と headers() が非同期になりました。
例:
// app/api/posts/[id]/route.ts
import { NextResponse } from 'next/server'
import { headers } from 'next/headers'
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params // ✅ Await params in Next.js 16
const headersList = await headers() // ✅ Await headers in Next.js 16
const post = await db.posts.findUnique({ where: { id } })
return NextResponse.json(post)
}
テンプレート:templates/route-handler-api.ts を参照してください。
Proxy と Middleware の違い
Next.js 16 では、middleware.ts に代わる proxy.ts が導入されました。
変更の理由
middleware.ts:Edge ランタイムで実行されます(Node.js API に制限があります)proxy.ts:Node.js ランタイムで実行されます(すべての Node.js API を利用できます)
新しい proxy.ts により、ネットワーク境界が明確になり、柔軟性が向上します。
移行
変更前(middleware.ts):
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Check auth
const token = request.cookies.get('token')
if (!token) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}
export const config = {
matcher: '/dashboard/:path*',
}
変更後(proxy.ts):
// proxy.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function proxy(request: NextRequest) {
// Check auth
const token = request.cookies.get('token')
if (!token) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}
export const config = {
matcher: '/dashboard/:path*',
}
テンプレート:templates/proxy-migration.ts
リファレンス:references/proxy-vs-middleware.md
Parallel Routes - default.js が必須(破壊的変更)
Next.js 16 での破壊的変更:Parallel Routes では、明示的な default.js ファイルが必須になりました。
構成:
app/
├── @modal/
│ ├── login/page.tsx
│ └── default.tsx ← REQUIRED in Next.js 16
├── @feed/
│ ├── trending/page.tsx
│ └── default.tsx ← REQUIRED in Next.js 16
└── layout.tsx
デフォルトファイル(必須):
// app/@modal/default.tsx
export default function ModalDefault() {
return null // or <Skeleton /> or redirect
}
必須になった理由:Next.js 16 では、ソフトナビゲーションの処理が変更されました。default.js がない場合、クライアント側のナビゲーション中に一致しないスロットでエラーが発生します。
テンプレート:templates/parallel-routes-with-default.tsx
React 19.2 の機能
Next.js 16 には React 19.2 が統合されており、React Canary の新機能が含まれています。
1. View Transitions
ユースケース:ページ遷移間のアニメーションをスムーズにします。
'use client'
import { useRouter } from 'next/navigation'
import { startTransition } from 'react'
export function NavigationLink({ href, children }: { href: string; children: React.ReactNode }) {
const router = useRouter()
function handleClick(e: React.MouseEvent) {
e.preventDefault()
// Wrap navigation in startTransition for View Transitions
startTransition(() => {
router.push(href)
})
}
return <a href={href} onClick={handleClick}>{children}</a>
}
CSS View Transitions API を使用する場合:
/* app/globals.css */
@view-transition {
navigation: auto;
}
/* Animate elements with view-transition-name */
.page-title {
view-transition-name: page-title;
}
テンプレート:templates/view-transitions-react-19.tsx
2. useEffectEvent()(実験的)
ユースケース:useEffect からリアクティブではないロジックを切り出します。
'use client'
import { useEffect, experimental_useEffectEvent as useEffectEvent } from 'react'
export function ChatRoom({ roomId }: { roomId: string }) {
const onConnected = useEffectEvent(() => {
console.log('Connected to room:', roomId)
})
useEffect(() => {
const connection = connectToRoom(roomId)
onConnected() // Non-reactive callback
return () => connection.disconnect()
}, [roomId]) // Only re-run when roomId changes
return <div>Chat Room {roomId}</div>
}
使用する理由:コールバックの依存関係が変更されたときに、不要な useEffect の再実行を防ぎます。
3. React Compiler(安定版)
ユースケース:useMemo や useCallback を使わずに、自動でメモ化します。
next.config.ts で有効にする:
import type { NextConfig } from 'next'
const config: NextConfig = {
experimental: {
reactCompiler: true,
},
}
export default config
プラグインをインストールする:
npm install babel-plugin-react-compiler
例(手動でのメモ化は不要です):
'use client'
export function ExpensiveList({ items }: { items: string[] }) {
// React Compiler automatically memoizes this
const filteredItems = items.filter(item => item.length > 3)
return (
<ul>
{filteredItems.map(item => (
<li key={item}>{item}</li>
))}
</ul>
)
}
リファレンス:references/react-19-integration.md
Turbopack(Next.js 16 で安定版)
新機能:Turbopack が Next.js 16 のデフォルトのバンドラーになりました。
パフォーマンスの向上:
- 本番ビルドが 2~5 倍高速
- Fast Refresh が最大 10 倍高速
無効にする(必要な場合):
npm run build -- --webpack
ファイルシステムキャッシュを有効にする(実験的):
// next.config.ts
import type { NextConfig } from 'next'
const config: NextConfig = {
experimental: {
turbopack: {
fileSystemCaching: true, // Beta: Persist cache between runs
},
},
}
export default config
よくあるエラーと解決方法
1. エラー:params が Promise です
エラー:
Type 'Promise<{ id: string }>' is not assignable to type '{ id: string }'
原因:Next.js 16 で params が非同期に変更されました。
解決方法:params を await します:
// ❌ Before
export default function Page({ params }: { params: { id: string } }) {
const id = params.id
}
// ✅ After
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
}
2. エラー:searchParams が Promise です
エラー:
Property 'query' does not exist on type 'Promise<{ query: string }>'
原因:Next.js 16 では searchParams が非同期になりました。
解決方法:
// ❌ Before
export default function Page({ searchParams }: { searchParams: { query: string } }) {
const query = searchParams.query
}
// ✅ After
export default async function Page({ searchParams }: { searchParams: Promise<{ query: string }> }) {
const { query } = await searchParams
}
3. エラー:cookies() に await が必要です
エラー:
'cookies' implicitly has return type 'any'
原因:Next.js 16 では cookies() が非同期になりました。
解決方法:
// ❌ Before
import { cookies } from 'next/headers'
export function MyComponent() {
const cookieStore = cookies()
}
// ✅ After
import { cookies } from 'next/headers'
export async function MyComponent() {
const cookieStore = await cookies()
}
4. エラー:Parallel Route に default.js がありません
エラー:
Error: Parallel route @modal/login was matched but no default.js was found
原因:Next.js 16 では、すべての Parallel Route に default.js が必要です。
解決方法:default.tsx ファイルを追加します:
// app/@modal/default.tsx
export default function ModalDefault() {
return null
}
5. エラー:revalidateTag() に 2 つの引数が必要です
エラー:
Expected 2 arguments, but got 1
原因:Next.js 16 では、revalidateTag() に cacheLife 引数が必要になりました。
解決方法:
// ❌ Before
revalidateTag('posts')
// ✅ After
revalidateTag('posts', 'max')
6. エラー:Server Component で React フックを使用できません
エラー:
You're importing a component that needs useState. It only works in a Client Component
原因:Server Component で React フックを使用しています。
解決方法:'use client' ディレクティブを追加します:
// ✅ Add 'use client' at the top
'use client'
import { useState } from 'react'
export function Counter() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(count + 1)}>{count}</button>
}
7. エラー:middleware.ts は非推奨です
警告:
Warning: middleware.ts is deprecated. Use proxy.ts instead.
解決方法:proxy.ts に移行します:
// Rename: middleware.ts → proxy.ts
// Rename function: middleware → proxy
export function proxy(request: NextRequest) {
// Same logic
}
8. エラー:Turbopack のビルドに失敗しました
エラー:
Error: Failed to compile with Turbopack
原因:Next.js 16 では Turbopack がデフォルトになりました。
解決方法:互換性がない場合は、Turbopack を無効にします:
npm run build -- --webpack
9. エラー:next/image の src が無効です
エラー:
Invalid src prop (https://example.com/image.jpg) on `next/image`. Hostname "example.com" is not configured under images in your `next.config.js`
解決方法:next.config.ts にリモートパターンを追加します:
const config: NextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
},
],
},
}
10. エラー:Server Component を Client Component にインポートできません
エラー:
You're importing a Server Component into a Client Component
解決方法:Server Component を children として渡します:
// ❌ Wrong
'use client'
import { ServerComponent } from './server-component' // Error
export function ClientComponent() {
return <ServerComponent />
}
// ✅ Correct
'use client'
export function ClientComponent({ children }: { children: React.ReactNode }) {
return <div>{children}</div>
}
// Usage
<ClientComponent>
<ServerComponent /> {/* Pass as children */}
</ClientComponent>
11. エラー:generateStaticParams が機能しません
原因:generateStaticParams は静的生成(export const dynamic = 'force-static')でのみ機能します。
解決方法:
export const dynamic = 'force-static'
export async function generateStaticParams() {
const posts = await fetch('/api/posts').then(r => r.json())
return posts.map((post: { id: string }) => ({ id: post.id }))
}
12. エラー:fetch() がキャッシュされません
原因:Next.js 16 では "use cache" ディレクティブによるオプトイン方式のキャッシュを使用します。
解決方法:コンポーネントまたは関数に "use cache" を追加します:
'use cache'
export async function getPosts() {
const response = await fetch('/api/posts')
return response.json()
}
13. エラー:Route Groups とのルートの競合
エラー:
Error: Conflicting routes: /about and /(marketing)/about
原因:Route Groups によって、同じ URL パスが作成されています。
解決策:Route Groups が競合しないようにしてください。
app/
├── (marketing)/about/page.tsx → /about
└── (shop)/about/page.tsx → ERROR: Duplicate /about
# Fix: Use different routes
app/
├── (marketing)/about/page.tsx → /about
└── (shop)/store-info/page.tsx → /store-info
14. エラー:メタデータが更新されない
原因:generateMetadata() を使用せずに動的なメタデータを使用しています。
解決策:動的ページには generateMetadata() を使用してください。
export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise<Metadata> {
const { id } = await params
const post = await fetch(`/api/posts/${id}`).then(r => r.json())
return {
title: post.title,
description: post.excerpt,
}
}
15. エラー:next/font のフォントが読み込まれない
原因:フォント変数が HTML 要素に適用されていません。
解決策:フォント変数を <html> または <body> に適用してください。
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'], variable: '--font-inter' })
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html className={inter.variable}> {/* ✅ Apply variable */}
<body>{children}</body>
</html>
)
}
16. エラー:環境変数をブラウザーで利用できない
原因:サーバー専用の環境変数はブラウザーに公開されません。
解決策:クライアント側からアクセスするには、NEXT_PUBLIC_ を接頭辞として付けてください。
# .env
SECRET_KEY=abc123 # Server-only
NEXT_PUBLIC_API_URL=https://api # Available in browser
// Server Component (both work)
const secret = process.env.SECRET_KEY
const apiUrl = process.env.NEXT_PUBLIC_API_URL
// Client Component (only public vars work)
const apiUrl = process.env.NEXT_PUBLIC_API_URL
17. エラー:Server Action が見つからない
エラー:
Error: Could not find Server Action
原因:'use server' ディレクティブがありません。
解決策:'use server' を追加してください。
// ❌ Before
export async function createPost(formData: FormData) {
await db.posts.create({ ... })
}
// ✅ After
'use server'
export async function createPost(formData: FormData) {
await db.posts.create({ ... })
}
18. エラー:TypeScript のパスエイリアスが機能しない
原因:tsconfig.json の baseUrl または paths が正しくありません。
解決策:正しく設定してください。
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./*"],
"@/components/*": ["./app/components/*"]
}
}
}
参考資料:references/top-errors.md
テンプレートとリソース
Next.js 16 専用テンプレート(templates/ 内):
app-router-async-params.tsx- Async params の移行パターンparallel-routes-with-default.tsx- 必須の default.js ファイルcache-component-use-cache.tsx-"use cache"を使用した Cache Componentsrevalidate-tag-cache-life.ts- cacheLife を使用する更新版revalidateTag()server-action-update-tag.ts- read-your-writes 用のupdateTag()proxy-migration.ts- middleware.ts から proxy.ts への移行view-transitions-react-19.tsx- React 19.2 の View Transitionsnext.config.ts- Next.js 16 の設定
同梱リファレンス(references/ 内):
next-16-migration-guide.md- Next.js 15 から 16 への完全な移行ガイドcache-components-guide.md- Cache Components の詳細解説proxy-vs-middleware.md- Proxy.ts と middleware.ts の比較async-route-params.md- Async params の破壊的変更の詳細react-19-integration.md- Next.js 16 における React 19.2 の機能top-errors.md- 18 件以上のよくあるエラーと解決策
外部ドキュメント:
- Next.js 16 ブログ:https://nextjs.org/blog/next-16
- Next.js ドキュメント:https://nextjs.org/docs
- Context7 MCP:最新のリファレンスは
/websites/nextjs
バージョン互換性
| パッケージ | 最小バージョン | 推奨 |
|---|---|---|
| Next.js | 16.0.0 | 16.0.0+ |
| React | 19.2.0 | 19.2.0+ |
| Node.js | 20.9.0 | 20.9.0+ |
| TypeScript | 5.1.0 | 5.7.0+ |
| Turbopack | (組み込み) | 安定版 |
バージョンの確認:
./scripts/check-versions.sh
トークン効率
推定トークン削減率:65~70%
スキルを使わない場合(ドキュメントを見ながら手動で設定):
- Next.js 16 移行ガイドを読む:約 5k トークン
- App Router ドキュメントを読む:約 8k トークン
- Server Actions ドキュメントを読む:約 4k トークン
- Metadata API ドキュメントを読む:約 3k トークン
- 試行錯誤による修正:約 8k トークン
- 合計:約 28k トークン
スキルを使う場合:
- スキルを読み込む:約 8k トークン
- テンプレートを使う:約 2k トークン
- 合計:約 10k トークン
- 削減量:約 18k トークン(約 64%)
防止できるエラー:よくある 18 件以上のミスを防止=エラーを 100% 防止
メンテナンス
最終確認日:2025-10-24 次回確認日:2026-01-24(四半期ごと) メンテナー:Jezweb | [email protected] リポジトリ:https://github.com/jezweb/claude-skills
更新の契機:
- Next.js のメジャー/マイナーリリース
- React のメジャーリリース
- API の破壊的変更
- Turbopack の新機能
バージョン確認:
cd skills/nextjs
./scripts/check-versions.sh
SKILL.md の終わり