Blog 一覧に戻る
Next.jsReactフロントエンド

Next.js App Router 完全ガイド — Pages Router からの移行ポイント

Next.js 13 以降の App Router は、Layouts・Server Components・Streaming など多くの新概念を導入しました。この記事では Pages Router との違いを整理しながら、実際の移行で躓きやすいポイントを解説します。

はじめに

Next.js 13 で導入された App Router は、これまでの Pages Router と大きく異なるアーキテクチャを持ちます。本記事では主要な変更点と、実際の移行で気をつけるべきポイントをまとめます。

Pages Router との主な違い

ファイル構成

Pages Router では pages/ ディレクトリにファイルを置くだけでルーティングされましたが、App Router では app/ ディレクトリを使い、page.tsx というファイル名が必須になります。

app/
├── page.tsx          # /
├── about/
│   └── page.tsx      # /about
└── blog/
    ├── page.tsx      # /blog
    └── [slug]/
        └── page.tsx  # /blog/:slug

Server Components がデフォルト

App Router では、コンポーネントはデフォルトで React Server Component (RSC) として扱われます。クライアント側の状態管理やイベントハンドラが必要な場合は、ファイルの先頭に 'use client' を明記する必要があります。

// サーバーコンポーネント(デフォルト)
export default async function Page() {
  const data = await fetch('https://api.example.com/data')
  return <div>{/* ... */}</div>
}

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

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

Layouts の入れ子構造

App Router の大きな特徴のひとつが、Nested Layouts です。各ディレクトリに layout.tsx を置くことで、そのディレクトリ以下のページに共通のレイアウトを適用できます。

// app/blog/layout.tsx
export default function BlogLayout({ children }: { children: React.ReactNode }) {
  return (
    <div className="max-w-3xl mx-auto">
      <nav>{/* ブログ内ナビ */}</nav>
      {children}
    </div>
  )
}

移行で躓きやすいポイント

getServerSideProps / getStaticProps の廃止

Pages Router で使っていたデータ取得関数は App Router では使えません。代わりに、Server Component 内で直接 async/await を使います。

// Pages Router (旧)
export async function getStaticProps() {
  const posts = await fetchPosts()
  return { props: { posts } }
}

// App Router (新)
export default async function BlogPage() {
  const posts = await fetchPosts()
  return <BlogList posts={posts} />
}

useRouter の import 元が変わる

// Pages Router
import { useRouter } from 'next/router'

// App Router
import { useRouter } from 'next/navigation'

環境変数のクライアント公開

App Router でもクライアント側に環境変数を公開するには NEXT_PUBLIC_ プレフィックスが必要ですが、Server Component では process.env.SECRET_KEY のようにプレフィックスなしの変数も安全に読めます。

まとめ

App Router への移行は一度に全てを変える必要はなく、Next.js は Pages Router と App Router の共存をサポートしています。まず新規ページを App Router で作り始め、徐々に既存ページを移行するアプローチが現実的です。