[Next.js] Page RouterからApp Routerへの乗り換え手順

2025/03/03

Next.js

こんにちは。

今回は、この企業ページのリポジトリをNext.js 13から15にアップデートしたので、その際に必要だった手順についてまとめてみました。

Next.js 13から15への移行ガイド

Next.js 13で導入されたApp Routerapp/ディレクトリを用いたルーティング)は、Next.js 13.4.0で正式に標準となりました。本記事では、Next.js 13から15への移行時に押さえておくべき技術的ポイントや具体的な移行手順について解説します。


1. ファイル構成の変更(Pages Router → App Router)

📌 変更点

  • pages/ディレクトリを廃止し、app/ディレクトリを使用。
  • ルーティングはファイル名ではなくディレクトリ構造で決まる。
  • page.tsx(ページコンポーネント)を各ディレクトリ内に配置。
  • layout.tsxを用いてページ間で共通レイアウトを適用。

📝 移行前後のディレクトリ構成

従来のPages Router

pages/
├── _app.tsx
├── _document.tsx
├── index.tsx  ("/"ページ)
├── about.tsx  ("/about"ページ)
├── posts/
│   └── [id].tsx  ("/posts/:id"ページ)
└── api/
    └── hello.ts  (APIエンドポイント)

新しいApp Router

app/
├── layout.tsx  (Root Layout)
├── page.tsx  ("/"ページ)
├── about/
│   └── page.tsx  ("/about"ページ)
├── posts/
│   └── [id]/
│       └── page.tsx  ("/posts/:id"ページ)
└── api/
    └── hello/
        └── route.ts  (APIエンドポイント)

🛠 移行手順

  1. app/ディレクトリを作成。
  2. pages/_app.tsxpages/_document.tsxの内容をapp/layout.tsxに移行。
  3. 各ページを対応するapp/配下にpage.tsxとして配置。
  4. pages/api/のAPIルートをapp/api/内にroute.tsとして移行。

2. API Routesの変更(pages/api/ → app/api/)

📌 変更点

  • pages/api/app/api/に移動。
  • APIエンドポイントの定義はroute.tsファイル内に記述。
  • req, resではなく、RequestオブジェクトとNextResponseを使用。

📝 移行前後のAPIルート

従来のAPIルート

pages/api/hello.ts
// pages/api/hello.ts
import { NextApiRequest, NextApiResponse } from 'next';

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  res.status(200).json({ message: 'Hello World' });
}

新しいAPIルート

app/api/hello/route.ts
// app/api/hello/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  return NextResponse.json({ message: 'Hello World' }, { status: 200 });
}

🛠 移行手順

  1. pages/api/の各ファイルをapp/api/配下に移動。
  2. ファイル名をroute.tsに変更。
  3. req, resの処理をNextResponseで置き換え。

3. Server Componentsの導入

📌 変更点

  • App RouterではデフォルトでServer Componentsが使用される。
  • クライアントコンポーネントは"use client"を明示的に追加。
  • getStaticPropsgetServerSidePropsは使用不可、代わりにサーバーコンポーネント内で直接データ取得。

📝 クライアントコンポーネントの例

// クライアントコンポーネント(ボタン)
'use client';
import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}

📝 サーバーコンポーネントでのデータ取得

app/news/page.tsx
// app/news/page.tsx
export default async function NewsPage() {
  const res = await fetch('https://api.example.com/news');
  const newsList = await res.json();

  return (
    <main>
      {newsList.map(item => <NewsItem key={item.id} data={item} />)}
    </main>
  );
}

🛠 移行手順

  1. useStateuseEffectを使用するコンポーネントに"use client"を追加。
  2. getStaticProps/getServerSidePropsを削除し、データ取得はサーバーコンポーネント内で行う。

4. 特殊ページの変更

📌 変更点

  • pages/404.tsxapp/not-found.tsx
  • pages/_error.tsxapp/error.tsx
  • ページ読み込み中の処理: loading.tsx(各ディレクトリ内に配置可能)

🛠 移行手順

  1. 404.tsxapp/not-found.tsxに移行。
  2. loading.tsxを適宜配置してローディング処理を追加。

5. メタデータと<head>の扱い

📌 変更点

  • <Head>コンポーネントの代わりにexport const metadataを使用。
  • head.tsxで動的なメタタグ設定も可能。

📝 メタデータの設定

app/layout.tsx
// app/layout.tsx
export const metadata = {
  title: 'My App',
  description: 'This is a Next.js 15 application',
};

🛠 移行手順

  1. 各ページの<Head>の内容をmetadataに移動。

6. 移行手順まとめ

  1. Next.jsを最新版(15系)にアップデート
npm install next@latest react@latest react-dom@latest
  1. app/ディレクトリを作成
  2. Root Layout(app/layout.tsx)を実装
  3. 各ページをapp/に移動
  4. データ取得をfetchに書き換え
  5. APIルートをapp/api/へ移動
  6. クライアントコンポーネントに"use client"を追加
  7. 特殊ページをリネーム
  8. メタデータをmetadataに移行
  9. 不要なpages/ディレクトリを削除

まとめ

Next.js 13から15への移行は、App Routerの導入を中心に大きな変更が含まれています。移行の際は、ファイル構成の変更、APIルートの修正、Server Componentsの活用を意識しながら進めるとスムーズです。

Next.js 15の新機能を活かし、より柔軟な開発体験とパフォーマンスの向上を目指しましょう!