はじめに
Next.js 13以降で導入されたApp Routerは、それまでのpagesディレクトリベースのルーティング(Pages Router)から大きく設計思想が変わりました。特に「Server ComponentsとClient Componentsの使い分け」「Route Groups」「Server Actions」は、App Router特有の概念でつまずきやすいポイントです。
本記事では、これらの基礎を整理します。
App Routerとは
Next.jsのApp Routerは、appディレクトリ配下のフォルダ構造がそのままURLのルーティングに対応する、ファイルシステムベースのルーターです。フォルダの中にpage.tsx(または.js)を置くことで、そのフォルダのパスに対応するページが定義されます。
app/
├── page.tsx → "/"
├── recipes/
│ ├── page.tsx → "/recipes"
│ └── [id]/
│ └── page.tsx → "/recipes/123" のような動的ルート
└── layout.tsx → 全ページ共通のレイアウト
[id]のように角括弧で囲んだフォルダ名は動的セグメントと呼ばれ、/recipes/1や/recipes/2のように可変のパスをまとめて1つのページ実装で扱えます。
また、layout.tsxは複数のページ間で共有されるUIを定義するファイルで、ページ遷移時にも再レンダリングされずに状態を保持します。
Server ComponentsとClient Components
App Routerの最も大きな特徴は、コンポーネントがデフォルトでサーバー上でレンダリングされるという点です。
Server Components(デフォルト)
appディレクトリ配下のコンポーネントは、特に指定しなければServer Componentとして扱われます。サーバー上でデータ取得・レンダリングを行い、結果(HTML)をクライアントに送るため、クライアント側に送信されるJavaScriptの量を減らせるというメリットがあります。DBへの直接アクセスや秘匿情報の扱いも、クライアントに露出させずにサーバー側だけで完結できます。
Client Components
一方で、useStateやuseEffectのようなReactのフック、クリックイベントのハンドリング、localStorageのようなブラウザAPIを使いたい場合は、ファイルの先頭に"use client"という指示(ディレクティブ)を書いてClient Componentとして明示する必要があります。
"use client"
import { useState } from "react"
export function Counter() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(count + 1)}>{count}</button>
}
"use client"は「このファイルの中身をクライアント側で動かす境界(バウンダリ)」を宣言するものであり、対話的なUI(状態管理・イベント処理)が必要な部分にだけ限定的に使うのが基本方針です。
Route Groups
Route Groupsは、(グループ名)のように括弧で囲んだフォルダを作ることで、URLのパスには影響を与えずにルートをグループ分けできる機能です。
app/
├── (auth)/
│ ├── login/
│ │ └── page.tsx → "/login"("(auth)"はURLに含まれない)
│ └── signup/
│ └── page.tsx → "/signup"
└── (app)/
├── layout.tsx → ヘッダー・サイドメニュー付きの共通レイアウト
└── dashboard/
└── page.tsx → "/dashboard"
この例では、ログイン前の画面群((auth))とログイン後の画面群((app))を別々のグループとして整理しつつ、URLはそれぞれ/login・/dashboardのようにグループ名を含まない形になります。グループごとに異なるlayout.tsxを持たせることで、「ログイン画面にはヘッダーを出さない」「ログイン後の画面にだけサイドメニューを出す」といった出し分けが自然に実現できます。
なお、異なるルートグループが同じURLパスに解決されてしまう場合(例:(a)/aboutと(b)/aboutが両方とも/aboutになる)はエラーになるため、グループ分けの際は最終的なパスが重複しないよう注意が必要です。
Server Actions
Server Actionsは、クライアント側のコンポーネントから直接呼び出せる、サーバー上で実行される非同期関数です。ファイルや関数の先頭に"use server"ディレクティブを付けることで定義します。
async function createRecipe(formData: FormData) {
"use server"
const title = formData.get("title")
// ここでDBへの保存処理などを行う
}
これを<form action={createRecipe}>のようにフォームへ直接渡すことで、従来は「フロントエンドからAPIエンドポイントを別途呼び出す」形で書いていたデータ更新処理を、専用のAPIルートを用意せずシンプルに実装できます。Server Actionsは内部的にHTTPのPOSTメソッドとして扱われ、渡す引数や戻り値はシリアライズ可能な値に限られるという制約があります。
まとめ
| 概念 | 内容 |
|---|---|
| App Router |
appディレクトリのフォルダ構造がそのままURLになる、ファイルシステムベースのルーター |
動的セグメント([id]) |
可変のパスパラメータを1つの実装でまとめて扱う仕組み |
| Server Components | デフォルトの動作。サーバー上でレンダリングされ、クライアントへのJS転送量を減らせる |
| Client Components |
"use client"で明示。状態管理やブラウザAPIが必要な対話的UIに使う |
| Route Groups |
(グループ名)でURLに影響を与えずルートを整理し、レイアウトを出し分けられる |
| Server Actions |
"use server"で定義する、クライアントから直接呼び出せるサーバー側の処理 |