🪄

【Next.js 14】 App Router と Pages Router の共存・移行

に公開

はじめに

Next.js 13 から新しい App Router が登場し、従来の Pages Router と大きく異なる仕組みを持ちます。公式も新規開発では App Router を推奨しています。
そして、Next.js 14 では、従来の Pages Router と新しい App Router を同一プロジェクト内で共存できます。既存の pages ディレクトリを維持しつつ、段階的に app ディレクトリへ移行することで、リリースリスクを抑えながら最新機能を取り込めます。

本記事ではそれぞれの特徴や違いを整理し、共存運用や段階的移行の実例を解説します。

バージョン要件

  • Node.js 18 以上が推奨
  • Next.js 14.x 系を利用すること

対象者

  • Next.js を既に pages ディレクトリで運用している人
  • App Router を一気に移行せず、ページ単位で段階的に導入したい人
  • React Server Components やレイアウト機能を安全に試したい人

App Router と Pages Router の違い

Pages Router とは

  • /pages ディレクトリにファイルを置くことでルーティングされる
  • ファイルベースルーティング (例: pages/about.tsx → /about)
  • Next.js 初期からの仕組みで利用実績が豊富
  • メリット: シンプルで学習コストが低い、情報が豊富
  • デメリット: レイアウト管理が単層的で複雑化しやすく、最新機能は非対応

App Router とは

  • /app ディレクトリに基づく新しいルーティングシステム
  • React Server Components (RSC) をデフォルトで採用
  • レイアウト・テンプレート・サーバーアクションなど最新の仕組みを活用可能
  • メリット: 柔軟なレイアウト構造、サーバー側での fetch、ストリーミングやキャッシュ戦略によるパフォーマンス改善が期待できる新機能に対応
  • デメリット: Pages Router からの移行難易度が高く学習コストが大きい

機能比較

項目 Pages Router App Router
ルーティング定義 pages/ ディレクトリにファイル配置 app/ ディレクトリにファイル配置
データ取得 getStaticProps / getServerSideProps サーバーコンポーネント内で直接 fetch 可能
レイアウト管理 _app.js, _document.js app/layout.tsx による階層的レイアウト
コンポーネント種別 すべてクライアントコンポーネント デフォルトがサーバーコンポーネント("use client" で明示可)
エラーハンドリング 各ページごとに try/catch 等で実装 error.tsx を置くとルート単位でエラーバウンダリ
ストリーミング 非対応 部分レンダリング・ストリーミングが標準
安定性 長年の実績がある Next.js 13 以降で追加され、14 で安定性が高まった

ディレクトリ構成の対比

このように、ディレクトリ構成レベルでも両者は明確に異なり、どちらを選ぶかで設計の指針が変わります。

📂 Pages Router の例

my-next-app/
├─ pages/
│  ├─ index.tsx
│  └─ posts/[slug].tsx
├─ public/
└─ next.config.js

📁 App Router の例

my-next-app/
├─ app/
│  ├─ layout.tsx
│  ├─ page.tsx
│  ├─ posts/
│  │  └─ [slug]/page.tsx
│  ├─ error.tsx
│  └─ loading.tsx
├─ public/
└─ next.config.js

使い分けの目安

  • Pages Router: 既存プロジェクトの延長で開発したい、小〜中規模、素早く立ち上げたい場合
  • App Router: 新規開発、パフォーマンスや将来性を重視、複雑なレイアウトやデータ読み込みが必要な場合

共存の基本原則

  • ディレクトリ構成

    • pages と app を同居させられる
    • 同じパスを両方に定義した場合、App Router 側が優先される
  • _app.js_document.js の役割は app/layout に統合できる

  • 併用のねらい

    • 影響範囲の小さい画面から App Router 化し、テスト済みになったら徐々に移行を広げる

共存の有用性

  • 一度に全ページを App Router に移す必要がない
  • Pages Router の安定性を活かしつつ、新規ページは App Router で実装できる
  • リリースリスクを下げながら最新機能を取り込める
  • チーム内で段階的に新機能を検証できる

既存の pages プロジェクトに app を段階的移行する手順

以下はブログサイトを例に、トップページのみ App Router へ置き換える手順です。

作業の前提

  • Node.js と Next.js のバージョン要件を満たす
  • 既存の pages と API の動作がグリーンであることを確認する
  • VCS で小さなコミットを刻み、差分を明確化する

1. プロジェクト直下に app ディレクトリを追加

my-next-app/
├─ pages/
│  ├─ index.tsx
│  └─ posts/[slug].tsx
├─ app/
│  └─ page.tsx
├─ public/
└─ next.config.js
  • app/page.tsx を追加すると、ルートパスは App Router が担当する
  • 既存の pages/index.tsx は残してよいが、同一ルートは app 側が優先される

2. app の基本ファイルを用意

  • グローバルレイアウト (例)
// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="ja">
      <body>{children}</body>
    </html>
  )
}
  • トップページ (例)
// app/page.tsx
export default function Home() {
  return <main>App Router のトップページ</main>
}

3. クライアントコンポーネントの指定

  • App Router ではデフォルトがサーバーコンポーネント
  • ブラウザ API やイベント処理を含む場合は、対象のコンポーネントファイル(例: app/page.tsx やコンポーネントファイル)の先頭にディレクティブを付与
"use client"

4. 注意事項

ルーティングの切り分け

  • まずは影響の小さい静的ページや新規ページから app へ
  • 既存の複雑なページは pages に残す
  • API ルートは当面 pages/api を継続し、将来必要に応じて app の Route Handler へ移行

同一パスの競合

  • pages と app に同じパスがあると app が優先される
  • 一時的に pages 側を利用したいケースでは、app 側の該当ファイルを一時リネームする運用も可能

pages/_app.jspages/_document.js の扱い

  • Pages Router 時代の _app_document で設定していた内容は、app/layout.tsx に移す必要がある
  • 共存期間は _app 側が残っていても動作はするが、グローバルスタイルやメタ情報を二重管理しないよう注意

まとめ

  • App Router と Pages Router は同一プロジェクトで共存できる
  • ルート競合時は App Router が優先される
  • 小さく導入し、落とし穴を回避しながら段階的に移行するのが実践的

おわりに

Next.js 13 以降の仕様変更に最初は戸惑いましたが、慣れてくるとよりシンプルで理解しやすい構造だと感じています。今回紹介した共存や段階的移行のアプローチは、すぐに全移行できない現場にとって現実的な選択肢となるはずです。
Next.js 13 以降の新方式にまだ慣れていない方にとって、本記事が参考になれば嬉しいです。


株式会社ONE WEDGE

【Serverlessで世の中をもっと楽しく】
ONE WEDGEはServerlessシステム開発を中核技術としてWeb系システム開発、AWS/GCPを利用した業務システム・サービス開発、PWAを用いたモバイル開発、Alexaスキル開発など、元気と技術力を武器にお客様に真摯に向き合う価値創造企業です。
https://onewedge.co.jp/

GitHubで編集を提案

Discussion