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 で作り始め、徐々に既存ページを移行するアプローチが現実的です。