0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIオンリーのコーディングでは Next.js 16 にアップデートしない方がいい

Last updated at Posted at 2025-12-08

TL;DR

  • 2025年12月時点、Claude Code や Cursor は Next.js 16 の破壊的変更を知らない
  • AI は middleware.ts を使おうとするが、Next.js 16 では proxy.ts にリネームされた
  • すでにアップデートした人は、この記事のリファレンスを AI に読ませれば対処可能

なぜこの記事を書いたか

Claude Code を使って Next.js プロジェクトを開発していたところ、Next.js 16 にアップデートした途端、AI が間違ったコードを生成するようになりました。

// AI が生成したコード(❌ 動かない)
// middleware.ts
export function middleware(request: NextRequest) {
  // ...
}

Next.js 16 では middleware.tsproxy.ts にリネームされています。

AI の学習データには Next.js 16 の情報がまだ十分に含まれていないため、こういった問題が発生します。


AI が間違えるポイント

1. middleware → proxy(最も危険)

Next.js 15 Next.js 16
middleware.ts proxy.ts
export function middleware() export function proxy()

AI は「Next.js の middleware を実装して」と言うと、古い書き方でコードを生成します。

2. params / searchParams の非同期化

// AI が生成しがち(❌ エラー)
export default function Page({ params }) {
  const { slug } = params;
}

// 正しい書き方(✅)
export default async function Page({ params }) {
  const { slug } = await params;
}

3. next lint の廃止

# AI が提案しがち(❌ 動かない)
npm run lint  # "next lint" を呼び出そうとする

# Next.js 16 の正解
npm run lint  # "eslint ." を直接実行

結論:AI オンリーなら Next.js 15 のままがいい

もしあなたが:

  • Claude Code や Cursor をメインで使っている
  • コードの大半を AI に書かせている
  • Next.js の内部をあまり理解していない

なら、Next.js 15 のままでいることをお勧めします

AI の学習データが追いつくまで(おそらく数ヶ月)、Next.js 16 は人間の監督が必要です。


すでにアップデートしてしまった人へ

対処法:リファレンスを AI に読ませる

以下の Markdown ファイルを docs/guides/NEXTJS16-QUICK-REFERENCE.md として保存してください。

AI に作業を依頼する前に、こう伝えてください:

このプロジェクトは Next.js 16 を使用しています。
docs/guides/NEXTJS16-QUICK-REFERENCE.md を読んで、
Next.js 16 の破壊的変更を理解してから作業してください。

Next.js 16 クイックリファレンス(コピペ用)

以下をそのままコピーして docs/guides/NEXTJS16-QUICK-REFERENCE.md として保存してください。

# Next.js 16 クイックリファレンス

> **更新日**: 2025-12-08
> **適用バージョン**: Next.js 16.0.7
> **目的**: Claude Code / Cursor などの AI コーディングツールに読ませて、Next.js 16 の破壊的変更を正しく理解させる

---

## AI コーディングツールをお使いの方へ

**2025年12月時点で、Claude Code や Cursor などの AI は Next.js 16 の変更点を十分に学習していません。**

そのため、AI は以下のような**間違ったコード**を生成する可能性があります:

-`middleware.ts` を作成しようとする(正しくは `proxy.ts`-`params` を同期的にアクセスする(正しくは `await params`-`next lint` コマンドを使用する(正しくは `eslint .`**このドキュメントを AI に読ませることで、正しいコードを生成させることができます。**

### AI への指示例

```
このプロジェクトは Next.js 16 を使用しています。
docs/guides/NEXTJS16-QUICK-REFERENCE.md を読んで、
Next.js 16 の破壊的変更を理解してから作業してください。
```

---

## 移行必須チェックリスト

Next.js 15 → 16 へのアップグレードで**必ず対応が必要な項目**:

| # | 項目 | 必須度 | 備考 |
|---|------|--------|------|
| 1 | `middleware.ts``proxy.ts` | ⚠️ **必須** | ファイル名・関数名の変更 |
| 2 | `params` / `searchParams` の非同期化 | ⚠️ **必須** | Server Component で `await` 必須 |
| 3 | `cookies()` / `headers()` の await | ⚠️ **必須** | 既に await していれば OK |
| 4 | `next lint``eslint .` | ⚠️ **必須** | package.json 修正 |
| 5 | React 19.2.1 以上 | ⚠️ **必須** | CVE-2025-55182 対策 |
| 6 | Parallel Routes の `default.js` | 条件付き | 使用している場合のみ |
| 7 | `revalidateTag` 新シグネチャ | 条件付き | 使用している場合のみ |

---

## 公式ドキュメント

| ドキュメント | URL |
|-------------|-----|
| **Next.js 16 公式ブログ** | https://nextjs.org/blog/next-16 |
| **アップグレードガイド** | https://nextjs.org/docs/app/guides/upgrading/version-16 |
| **CVE-2025-66478 セキュリティアドバイザリ** | https://nextjs.org/blog/CVE-2025-66478 |

---

## 日本語解説記事

| 記事 | URL |
|------|-----|
| **TECHSCORE: Next.js 16 移行ガイド** | https://blog.techscore.com/entry/2025/12/01/080000 |

---

## 主要な変更点

### 1. middleware.ts → proxy.ts(最重要)

**AI が最も間違えやすいポイントです。**

Next.js 16 で **Middleware は Proxy に名称変更**されました。`middleware.ts` は存在しません。

#### 変更手順

```bash
# 1. ファイル名変更
mv middleware.ts proxy.ts

# 2. 関数名変更(エディタで)
# export function middleware → export function proxy
```

#### コード変更

```typescript
// ❌ Before (Next.js 15) - middleware.ts
// このファイルは Next.js 16 では動作しません!
export function middleware(request: NextRequest) {
  return NextResponse.next();
}

// ✅ After (Next.js 16) - proxy.ts
// ファイル名も関数名も "proxy" です
export function proxy(request: NextRequest) {
  return NextResponse.next();
}
```

#### config の変更(該当する場合のみ)

```typescript
// ❌ Before (Next.js 15)
skipMiddlewareUrlNormalize: true,

// ✅ After (Next.js 16)
skipProxyUrlNormalize: true,
```

#### matcher 設定例

```typescript
// proxy.ts
export const config = {
  matcher: [
    '/',
    '/((?!api|_next/static|_next/image|favicon.ico|manifest\\.json|sw\\.js|.*\\.(?:svg|png|jpg|jpeg|gif|webp|html)$).*)',
  ],
};
```

#### 注意点

1. **静的ファイルの除外**: matcher で静的ファイル(画像、CSS、JS)を除外しないとパフォーマンスが低下
2. **API Routes の除外**: `/api/*` は proxy から除外(各エンドポイントで認証処理)
3. **サブドメイン処理**: サブドメインは proxy 内でリライト処理

---

### 2. 非同期 API 必須化(重要)

**AI が古いコードを生成しやすいポイントです。**

Next.js 16 では、Server Component での `params``searchParams``cookies()``headers()` へのアクセスが**非同期必須**になりました。

#### 2.1 params の非同期化

```typescript
// ❌ Before (同期アクセス - Next.js 16 ではエラー)
// AI がこのコードを生成したら修正してください
export default function Page({ params }) {
  const { slug } = params;  // エラー!
}

// ✅ After (非同期 - Next.js 16 必須)
export default async function Page({ params }) {
  const { slug } = await params;  // OK
}

// ✅ または Promise 型を明示
export default async function Page({
  params
}: {
  params: Promise<{ slug: string }>
}) {
  const { slug } = await params;
}
```

#### 2.2 searchParams の非同期化

```typescript
// ❌ Before - AI がこのコードを生成することがあります
export default function Page({ searchParams }) {
  const query = searchParams.q;  // エラー!
}

// ✅ After (Next.js 16)
export default async function Page({ searchParams }) {
  const { q } = await searchParams;
}
```

#### 2.3 cookies() / headers() の非同期化

```typescript
import { cookies, headers } from 'next/headers';

// ❌ Before (Next.js 15 では動作していた)
const cookieStore = cookies();
const value = cookieStore.get('name');

// ✅ After (Next.js 16 必須)
const cookieStore = await cookies();
const value = cookieStore.get('name');

// headers も同様
const headersList = await headers();
const userAgent = headersList.get('user-agent');
```

#### 2.4 Client Component では影響なし

```typescript
'use client';

// Client Component では useParams() を使用(変更なし)
import { useParams, useSearchParams } from 'next/navigation';

export default function ClientPage() {
  const params = useParams();        // ✅ 同期的に動作
  const searchParams = useSearchParams();  // ✅ 同期的に動作
  return <div>{params.slug}</div>;
}
```

---

### 3. Turbopack デフォルト化

```bash
# 開発サーバー(Turbopack がデフォルト)
npm run dev

# Webpack に戻す場合(互換性問題がある場合)
npm run dev -- --webpack
npm run build -- --webpack
```

**パフォーマンス改善**:
- ビルド: 2-5倍高速
- Fast Refresh: 最大10倍高速

---

### 4. ESLint(重要)

**`next lint` コマンドは廃止されました。**

#### 変更が必要な箇所

**package.json**:
```json
{
  "scripts": {
    //  Before (Next.js 15) - 動作しません
    "lint": "next lint",

    //  After (Next.js 16)
    "lint": "eslint ."
  }
}
```

#### ESLint 設定ファイル

Next.js 16 では **Flat Config (eslint.config.mjs)** を推奨:

```javascript
// eslint.config.mjs
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const compat = new FlatCompat({
  baseDirectory: __dirname,
});

export default [
  ...compat.extends("next/core-web-vitals", "next/typescript"),
  {
    rules: {
      // カスタムルール
    },
  },
];
```

---

### 5. キャッシュコンポーネント

```typescript
// next.config.ts
const nextConfig = {
  cacheComponents: true,
};

// 使用例
'use cache';

export default async function Page() {
  const data = await fetchData();
  return <div>{data}</div>;
}
```

---

### 6. revalidateTag 新シグネチャ

```typescript
// ❌ Before
revalidateTag('blog-posts');

// ✅ After (cacheLife プロファイル必須)
revalidateTag('blog-posts', 'max');
revalidateTag('news-feed', 'hours');
```

---

### 7. updateTag / refresh(新API)

```typescript
'use server';
import { updateTag, refresh } from 'next/cache';

// 即座に変更を反映(Server Actions 専用)
export async function updateProfile(userId: string) {
  await db.users.update(userId, ...);
  updateTag(`user-${userId}`);
}

// キャッシュされていないデータのみ更新
export async function markAsRead(id: string) {
  await db.notifications.markAsRead(id);
  refresh();
}
```

---

### 8. next/image 変更

| 設定 | v15 デフォルト | v16 デフォルト |
|------|---------------|---------------|
| `minimumCacheTTL` | 60秒 | 14400秒 (4時間) |
| `imageSizes` | [16, 32, ...] | [32, ...] (16削除) |
| `qualities` | [1-100] | [75] |
| `maximumRedirects` | 無制限 | 3 |

---

### 9. Parallel Routes

すべてのスロットに `default.js` が必須:

```tsx
// app/@modal/default.tsx
export default function Default() {
  return null;
}
```

---

## 環境要件

| 要件 | 最小バージョン |
|------|----------------|
| Node.js | 24.5.0 |
| TypeScript | 5.1.0+ |
| Chrome | 111+ |
| Edge | 111+ |
| Firefox | 111+ |
| Safari | 16.4+ |

---

## セキュリティ対応

### React CVE-2025-55182 (React2Shell)

- **影響**: React Server Components の unsafe deserialization
- **CVSS**: 10.0(最大)
- **対応**: React 19.2.1 で修正済み

### Next.js CVE-2025-66478

- **対応**: Next.js 16.0.7 で修正済み

---

## AI への指示テンプレート

以下をコピーして AI に伝えてください:

```
# Next.js 16 プロジェクトの注意事項

このプロジェクトは Next.js 16 を使用しています。以下の点に注意してください:

1. **middleware は proxy にリネームされています**
   - ファイル: middleware.ts → proxy.ts
   - 関数: middleware() → proxy()

2. **Server Component の params/searchParams は非同期です**
   - const { slug } = await params; // await 必須

3. **cookies()/headers() も非同期です**
   - const cookieStore = await cookies();

4. **ESLint は直接実行します**
   - npm run lint は "eslint ." を実行

詳細は docs/guides/NEXTJS16-QUICK-REFERENCE.md を参照してください。
```

---

## よくある問題と解決策

| 問題 | 原因 | 解決策 |
|------|------|--------|
| `middleware is not defined` | proxy.ts なのに middleware() を参照 | 関数名を proxy() に修正 |
| `params is a Promise` | 同期アクセスしている | await params に修正 |
| `next lint: command not found` | next lint 廃止 | eslint . を使用 |
| ビルドが遅い | Webpack にフォールバック | --webpack を削除してTurbopack使用 |

まとめ

  1. AI オンリーなら Next.js 15 で待機が安全
  2. すでにアップデートした人は上記リファレンスを AI に読ませる
  3. 人間の監督があるなら Next.js 16 でも問題なし

AI の学習データが追いつくまでの数ヶ月、この記事が役に立てば幸いです。


参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?