5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js App Routerの基本的な挙動と注意点

Last updated at Posted at 2025-12-24

この記事はmofmof Advent Calendar 2025の記事です。

直近のプロジェクトでNext.js App Routerを使うことが多かったので、おさらいも兼ねて基本的な挙動を書いてみます。
App Routerの大きな要素であるServer Components・Client Components・Server Functionsについて書いていきますが全体的にふんわりしています。

Server Components

Next.js(App Router)でコンポーネントを作成するとデフォルトはServer Componentsになります。
Server Componentsはサーバー上で実行されるコンポーネントです。

レンダリングについて

初回レンダリング(直アクセス・リロードなど)

サーバー側でServer Componentsが実行され実行結果として以下が生成されます。

  • HTML
  • RSC Payload(後述)

ブラウザにはまずHTMLが返され描画されるためSSRのような振る舞いとなります。

2回目以降のレンダリング(navigationやrefreshが行われた場合)

サーバー側でServer Componentsが実行されます。
初回とは異なりHTMLではなくRSC Payloadのみ返却され、クライアント側のReactがRSC Payloadをもとに再レンダリングを行います。

※RSC Payloadとは再レンダリングに必要なデータをまとめたRSC専用のデータ構造です。

Client Components

"use client"ディレクティブを付けたコンポーネントはClient Componentsになります。
Client Componentsは、最終的にブラウザ上で動作するReactコンポーネントです。

レンダリング

初回レンダリング(直アクセス・リロードなど)

初回アクセス時は、Client Componentsもサーバー側で一度実行され、以下が生成・配信されます。

  • HTML
  • RSC Payload
  • クライアント用のJavaScript

サーバー側での実行時は以下のような制約があります。

  • useStateなどのstateは初期値で描画される
  • windowdocumentなどのブラウザ APIは使用できない
  • useEffectは実行されない

まずはサーバーで生成されたHTMLが表示されその後ブラウザ上でHydrationが行われます。
Hydration とはHTMLとReactを紐づける処理で、以下のような処理が行われます。

  • stateとDOMの紐づけ
  • onClickなどのイベントハンドラの登録
  • useEffectの初回実行

Hydration後のレンダリング(Props / State の更新など)

Hydrationが完了したClient Componentsは基本的に通常のReact Componentと同様に振る舞います。

Client Components単体で見た場合、再レンダリングはすべてクライアント上で完結し、サーバーとの通信は発生しません。
(親のServer Componentが再レンダリングされた場合、新しいPropsがサーバーから渡されることはあります)

Next.js固有の制約(Server Componentsをimportできない等)を除けば、Hydration完了後のClient Componentsは純粋なReact Componentと考えて問題ないと思います。

注意点:Client Componentsに渡すProps

Client Componentsに渡したPropsはすべてクライアント側に公開されます。
Client Componentsをブラウザで実行するためにPropsがシリアライズされて渡されるためです。

極端な例ですが、以下のようなコードを書いた場合secretTokenはクライアントから確認できる状態になります。

"use client";

export function UserPreview({ object }: { object: Record<string, string> }) {
  return <div>{object.name}</div>;
}
async function getUser() {
  return {
    id: "1",
    name: "Taro",
    secretToken: SECRET_TOKEN,
  };
}

export default async function Page() {
  const user = await getUser();

  return <UserPreview object={user} />;
}

Client Components に渡すPropsは本当に必要なものだけに絞り、公開されても問題ない情報か確認する必要があります。

Server Functions

"use server" ディレクティブを付けることでクライアント側からサーバー上の関数を呼び出せる仕組みです。
少し前まではServer Actionsと呼んでいましたがServer Functionsという概念の中にServer Actionsが含まれる形に変わったようです。
こちらの記事の解説が分かりやすかったです。

関数を呼び出す感覚ですが実態としてはPOSTリクエストを利用して呼び出しています。
ここら辺はこちらの記事が詳細に書かれていて分かりやすかったです。

注意点

関数呼び出しの感覚ですが、クライアントから呼び出す場合は実行環境が変わるためAPIエンドポイントと同様に扱う必要があります。

  • 入力値のバリデーションを行う
  • 認証・認可チェックを行う
  • etc...

まとめ

  • Server Componentsは常にサーバーで実行され、初回はHTML、以降はRSC Payloadを通じて描画される
  • Client Componentsは初回のみSSRとHydrationが行われ、その後は基本的にクライアントで完結する
  • Client Componentsに渡したPropsはすべてクライアントに公開される
  • Server FunctionsはAPIエンドポイントと同様に各種検証などを行う
5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?