React Server Components(RSC)はブラウザに自身の JavaScript を 1 バイトも送りません。 サーバー上でのみ実行され、HTML をクライアントにストリーミングし、API レイヤーなしで 直接データを取得できます。Next.js App Router では、すべてのコンポーネントがデフォルトで Server Component です。このガイドではメンタルモデル、サーバーとクライアント間の境界、 大規模で機能するパターンを解説します。
核心的なアイデア
RSC 以前は、すべての React コンポーネントが JavaScript をブラウザに送っていました。 データベースの行を取得し、日付をフォーマットし、カードをレンダリングするコンポーネントは データベースドライバー・日付ライブラリ・レンダリングロジックをすべてブラウザバンドルに 含めていました — ブラウザはデータベースを呼び出さないのに。
RSC はこれを変えます: Server Components はサーバー上でのみ実行されます。出力は特殊な 形式(RSC ペイロード)にシリアライズされクライアントにストリーミングされます。クライアントは レンダリングされた HTML と小さな調整ペイロードを受け取ります — コンポーネントのソースコードではなく。
Server vs Client Components
| 機能 | Server Component | Client Component |
|---|---|---|
| サーバーで実行 | はい | はい(ハイドレーション) |
| クライアントで実行 | いいえ | はい |
| ブラウザに JS を送信 | いいえ | はい |
| DB/ファイルシステムへの直接アクセス | はい | いいえ |
| useState、useEffect | いいえ | はい |
| イベントハンドラー(onClick など) | いいえ | はい |
ファイルの先頭に "use client" を追加して Client Component としてマークします。 これがオプトイン境界です。Client Component を インポートするすべてのコンポーネントも クライアントバンドルの一部になります — 境界は下方向に伝播します。
Server Components でのデータ取得
Server Components は async 関数になれます。データを直接 await できます。useEffect も、ローディング状態も、API ルートも 不要です。コンポーネントは取得中に中断し、React は準備ができたら結果をクライアントに ストリーミングします。待機中のフォールバックを表示するには <Suspense> でラップします。
Suspense ストリーミングパターン
Suspense 境界により Next.js は HTML をチャンクでストリーミングできます。速いコンポーネントは すぐにレンダリングされて送信され、遅いものは後でレンダリングされて既に描画されたシェルに ストリーミングされます。ユーザーは空白画面の後の突然の全描画ではなく、段階的に完成する ページを見ます。
一般的なパターン
サーバーデータを props として Client Components に渡す
Server Components は Client Components をインポートしてデータを渡せます。データは シリアライズされ(JSON シリアライズ可能である必要があります — クラスインスタンス・関数は不可) props として渡されます。
イベントハンドラーは Client Components に保持する
onClick・onChange・useState・ブラウザ API を使う コンポーネントは "use client" とマークする必要があります。これらのコンポーネントを 小さく保ち、コンポーネントツリーの葉に向けて押し下げ、バンドルサイズを最小化します。
パフォーマンスへの影響
RSC を採用した実際の Next.js アプリでは、以前にクライアントサイドでデータを取得していた ページで JavaScript バンドルサイズが 30〜60% 削減されます。初期 HTML にローディング スケルトンではなく実際のコンテンツが含まれるため LCP が改善されます。ロード時にブラウザが パースして実行する JavaScript が少なくなるため INP も改善されます。