React Server Componentsとは|仕組みとクライアントとの違い
最終更新日:2026/10/13
React Server Componentsとは、コンポーネントをサーバー側だけで実行し、結果をクライアントへ送るReactの仕組みです。SSRの置き換えではなく、クライアント側で必要な部分にだけ「use client」で境界を作ります。App Routerで境界設計に手が止まる人向けに、仕組みと違い、実装で詰まる箇所を整理します。
先に結論
React Server Components(以下RSC)はサーバーでのみ実行されるコンポーネントで、クライアントへ送るJavaScriptを減らせます
サーバー用のディレクティブはありません。目印を付けるのはクライアント側の「use client」です
RSCはSSRの置き換えではありません。RSCペイロードという中間形式を挟み、フレームワークがそれを使って初回表示用のHTML生成やクライアント側の復元を行います
境界設計の要点は2つ。「use client」をツリーの下へ下げることと、propsをシリアライズ可能な値に限ることです
素のReactだけでは使えません。RSC対応のフレームワーク・バンドラー(Next.js App Router、React Routerの実験的サポート等)が前提になります
この記事でわかること
RSCの定義と、サーバーで動く仕組み(RSCペイロード・初回ロードの流れ)
クライアントコンポーネントとの違い、「use client」を付ける/付けない判断基準
SSR・SSG・CSRとの関係の整理
実装で詰まりやすい落とし穴5つと回避策
RSCを採用すべきプロジェクトと、見送ったほうがよいケース
対象はReactの実務経験が1年以上あり、App Routerや「use client」に触れ始めた段階のエンジニアです。Reactそのものの入門は「Reactとは?初心者向け入門解説|できること・人気の理由まで」で扱っています。
目次
React Server Componentsとは
クライアントコンポーネントとの違い
SSR・SSG・CSRとの違いを整理する
サーバーとクライアントをまたぐ実装パターン
実装で詰まりやすい落とし穴5つ
RSCを採用すべきか、見送るべきか
フリーランスエンジニアがRSC案件で確認すること
学習と移行の進め方
実践チェックリスト
まとめ
よくある質問
React Server Componentsとは
結論として、RSCはコンポーネントの実行環境をサーバー側に移すための仕組みです。条件として、RSCに対応したフレームワークまたはバンドラーが必要になります。例外的に、学習目的で対応テンプレートを使う場合も同じ前提が適用されます。
サーバーだけで実行されるコンポーネント
React公式のServer Componentsリファレンスは、RSCを「クライアントアプリやSSRサーバーとは別の環境で、バンドルより前にあらかじめレンダリングされる新しい種類のコンポーネント」と定義しています。
ポイントは実行環境の分離です。サーバーで完結する処理はクライアントに届きません。
たとえばマークダウンをHTMLへ変換する処理をサーバー側に置けば、変換ライブラリ自体をブラウザへ送る必要がなくなります。公式ドキュメントでは、この構成でクライアントバンドルから75KB(gzip後)を削れた例が示されています。削減量は依存ライブラリ次第ですが、重い依存を境界の向こうへ追い出せるという性質は共通です。
また、RSCはasync関数として書けます。コンポーネントの中で直接awaitしてDBやAPIを叩けるため、取得専用のAPIエンドポイントを用意する手間が減ります。useEffectで取得してから再描画する、という往復(ウォーターフォール)も発生しません。
RSCペイロードとは何か
RSCの描画結果はHTMLではありません。RSCペイロードと呼ばれる専用の直列化形式です。
Next.js公式ドキュメントによると、RSCペイロードには次の3つが入ります。
含まれるもの | 役割 |
|---|---|
Server Componentsの描画結果 | サーバーで確定したUIの内容 |
クライアントコンポーネントの差し込み位置とJSファイルへの参照 | どこを後からインタラクティブにするかの指示 |
サーバーからクライアントへ渡されたprops | 境界をまたいだデータ |
HTMLではなく構造化された中間形式を挟むのが、従来のSSRとの大きな違いです。この中間形式により、対応フレームワークでは画面遷移時にHTML全体ではなくReactツリーの更新を中心に扱いやすくなります。
ビルド時に動かすか、リクエストごとに動かすか
RSCの実行タイミングは2通りあります。公式はこれを明確に分けて説明しています。
ビルド時:CMSやマークダウンなど静的な内容を読む場合。Webサーバーは不要で、結果はCDNに置けます
リクエスト時:DBの最新データやログイン情報を扱う場合。アクセスごとにサーバーで実行されます
同じコンポーネントの書き方でタイミングだけが変わるため、どちらで動いているかを意識しないままキャッシュ設計に進むと事故ります。落とし穴の章で改めて触れます。
ミニFAQ:RSCを使うとクライアントのJavaScriptはゼロになりますか?
なりません。インタラクションを持つ部分はクライアントコンポーネントとして残り、そのJSは配信されます。減るのは「サーバーで完結させた処理とその依存ライブラリ」の分だけです。
クライアントコンポーネントとの違い
短答です。サーバーコンポーネントはデータ取得と静的な描画に向き、クライアントコンポーネントは状態とイベント処理に向きます。以下は執筆時点のReact公式リファレンスとNext.js公式ドキュメントの記載を整理したものです。
実行環境・できること・できないこと
観点 | サーバーコンポーネント | クライアントコンポーネント |
|---|---|---|
実行環境 | サーバー(ビルド時またはリクエスト時) | ブラウザ(Next.js App Routerなどでは初回表示時にサーバー側で事前描画されることがある) |
クライアントJSバンドル | 含まれない | 含まれる |
ディレクティブ | 不要(App Routerでは既定) | ファイル先頭に「use client」 |
async/await | 使える | 原則使わない(useやSuspenseで受ける) |
useState・useEffect | 使えない | 使える |
onClick等のイベント | 書けない | 書ける |
localStorage・window | 使えない | 使える |
APIキー・DB接続 | 扱える | 扱ってはいけない |
Contextの作成 | できない | できる |
「use client」は宣言ではなく境界
ここが最もつまずく箇所です。「use client」はそのファイル1枚をクライアント化する指示ではありません。公式リファレンスは、モジュール依存ツリーに境界を作ると説明しています。
つまり、「use client」を書いたファイルがimportしているモジュールと、その先の依存も推移的にクライアント側へ入るということです。ボタン1つのために親レイアウトへ「use client」を付けると、配下のほぼ全部がクライアントバンドルに流れ込みます。
逆に、childrenなどpropsとして渡されたサーバーコンポーネントは、クライアントコンポーネントのモジュールグラフに入りません。importしていないからです。この違いが、後述する「スロット」パターンの根拠になっています。
おもしろいのは、ディレクティブを持たないファイルの扱いです。サーバー側からimportされればサーバーで動き、クライアント側からimportされればクライアントで動きます。コンポーネントの定義ではなく、呼び出し元が環境を決めます。
どちらを選ぶかの判断基準
Next.js公式は用途ベースで整理しています。迷ったら次の順で考えると早いです。
状態・イベントハンドラ・useEffect・ブラウザ専用APIのいずれかが必要か → 必要ならクライアント
DBやAPIへ直接アクセスするか、APIキーを使うか → 使うならサーバー
どちらでもないか → サーバーのまま置く(既定がサーバーなので何もしない)
3番目を徹底できるかで、バンドルサイズが変わります。大きなSVGや表組みのような静的UIにまで「use client」が付いている実装は、レビューで指摘したい典型です。
SSR・SSG・CSRとの違いを整理する
結論を先に書くと、RSCとSSRは比較対象ではなく、重なるレイヤーが違います。RSCは「どこでコンポーネントを実行するか」の話で、SSR・SSG・CSRは「どこでHTMLを生成するか」の話です。
RSCはSSRの置き換えではない
Next.jsのApp Routerでは、サーバーコンポーネントがRSCペイロードへ描画され、そのペイロードとクライアントコンポーネントからHTMLが事前生成されます。RSCを使っていてもSSRは働いています。
クライアント側の初回ロードは3段階です。
HTMLで非インタラクティブな画面を即座に表示する
RSCペイロードでサーバー側ツリーとクライアント側ツリーを突き合わせる
JavaScriptでクライアントコンポーネントをハイドレートし、操作可能にする
2回目以降の遷移では、RSCペイロードがプリフェッチ・キャッシュされ、サーバー生成HTMLを経由せずに差し替わります。
レンダリング方式との対応関係
用語 | 何を決めるか | RSCとの関係 |
|---|---|---|
RSC | コンポーネントの実行環境 | サーバー側で実行し、結果をペイロード化する |
SSR | HTMLの生成場所と時点 | RSCペイロードを使ってHTMLを作る工程 |
SSG/ISR | HTMLの事前生成と再生成 | ビルド時実行のRSCと組み合わせやすい |
CSR | ブラウザでの描画 | クライアントコンポーネントが担う |
SSR・SSG・ISRの使い分けそのものは「Next.jsとは?React基盤のフレームワークの特徴・できること・年収・将来性をフリーランス視点で解説」で詳しく整理しています。本記事はRSCの境界設計に絞ります。
サーバーとクライアントをまたぐ実装パターン
境界をまたぐときの作法は、ほぼ3パターンに集約されます。
propsで渡せるデータ・渡せないデータ
サーバーからクライアントへ渡すpropsは、Reactがシリアライズできる値に限られます。公式リファレンスの一覧を整理します。
渡せる | 渡せない |
|---|---|
string、number、bigint、boolean、undefined、null | 「use server」でない通常の関数 |
Symbol.forで登録したグローバルSymbol | グローバル登録されていないSymbol |
Array、Map、Set、TypedArray、ArrayBuffer | クラスとそのインスタンス |
Date、プレーンオブジェクト | nullプロトタイプのオブジェクト |
Promise、JSX要素、Server Functions | イベントハンドラが受け取るevent |
実務で踏みやすいのは関数とクラスインスタンスです。サーバー側で組み立てたコールバックをonClickへ渡そうとすると、そこで落ちます。ORMが返すモデルのインスタンスをそのまま渡す実装も同じ理由で失敗します。境界をまたぐ直前でプレーンオブジェクトへ落とすのが定石です。
Promiseを渡せる点は見落とされがちです。サーバー側でawaitせずにPromiseを渡し、クライアント側でReactのuse関数で受け取れば、取得完了を待たずに画面を返せます。Suspenseのfallbackと組み合わせる形になります。
childrenをスロットにして差し込む
クライアントコンポーネントのモジュールから、サーバーコンポーネントを直接importすることはできません。一方で、親のサーバー側からchildrenなどのpropsとして渡す形は可能です。モジュール依存の話とレンダーツリーの話が別だから、と覚えておくと混乱しません。
モーダルやタブのような「状態は持つが中身は静的」なUIで効きます。外枠だけをクライアントコンポーネントにして、中身のサーバーコンポーネントを親から流し込みます。サーバー側で描画済みの結果がペイロードに乗るため、中身のコードはクライアントへ出ていきません。
Context Providerはできるだけ深くに置く
ContextはRSCでは作れません。「use client」を付けたProviderコンポーネントを用意し、サーバーコンポーネント側からレンダリングします。
Next.js公式は、Providerをツリーの可能な限り深い位置に置くよう勧めています。html要素ごと包んでしまうと、静的な部分の最適化が効きにくくなるためです。
Server Functions(「use server」)との関係
RSCとセットで語られるのがServer Functionsです。「use server」を付けた非同期関数で、フォーム送信や更新処理をサーバーで実行します。サーバーコンポーネントが「読み」を担い、Server Functionsが「書き」を担う構図です。
セキュリティの扱いは注意が必要です。公式リファレンスは、Server Functionsを「公開されたサーバーエンドポイントであり、クライアントコードのどこからでも呼び出せる」と明記しています。引数は完全にクライアント側の制御下にあるため、信頼できない入力として検証・エスケープすること、そしてログイン中のユーザーがその操作を行ってよいか毎回認可チェックすることが求められます。あわせて、CSRF対策やレート制限などの扱いはフレームワーク側の推奨実装に従ってください。
なお「use server」の引数・戻り値はReact要素やJSXを受け付けません。「use client」のpropsとは許容される型が違うので、同じシリアライズ制約だと思って設計すると引っかかります。
型安全なAPI設計の選択肢としてServer Functionsを比較検討する場合は、「tRPCとは|型安全なAPIの仕組み・使い方・GraphQL/RESTとの違い」も参考になります。
ミニFAQ:Server FunctionsがあればREST APIは不要になりますか?
自社フロントからの呼び出しだけなら減らせます。ただしモバイルアプリや外部連携の入口が必要なら、従来のAPIは残ります。Server Functionsは「このUIから呼ぶ処理」に閉じた手段と考えるのが安全です。
実装で詰まりやすい落とし穴5つ
ここは公式ドキュメントに並んでいない形で整理します。レビューや障害調査で実際に問題になりやすい順に並べました。
1. 「use client」がツリーの上方へ侵食する
症状は「RSCにしたのにバンドルが小さくならない」。原因はほぼ、上位のレイアウトやページに「use client」が付いていることです。
対処はシンプルです。インタラクティブな末端のファイルにだけ付け直します。検索ボックス付きのヘッダーなら、ヘッダー全体ではなく検索ボックスだけをクライアント化します。
2. シリアライズできないpropsでビルドが落ちる
関数・クラスインスタンス・未登録のSymbolが境界をまたぐと失敗します。エラーメッセージが出る場所と原因の場所が離れやすく、調査に時間を取られます。
境界に渡す値の型をTypeScriptで明示的に定義しておくと、実行前に気づけます。
3. サーバー専用コードがクライアントへ漏れる
モジュールはサーバーとクライアントで共有できます。だからこそ、APIキーを含む処理をうっかりクライアントコンポーネントからimportできてしまいます。
Next.jsでは、NEXT_PUBLIC_接頭辞のない環境変数はクライアントバンドルに含まれず、空文字へ置き換わります。動かないという形で気づけますが、気づけるだけです。公式はserver-onlyパッケージをサーバー専用モジュールにimportしておく方法を案内しています。これでクライアント側から参照した時点でビルドエラーになります。
機密値そのものの受け渡しを防ぎたい場合は、実験的APIのexperimental_taintUniqueValueやexperimental_taintObjectReferenceも用意されています。実験的である点は踏まえて採用判断してください。
4. サードパーティのUIライブラリが境界に対応していない
useStateを使っているのに「use client」が付いていないパッケージは、サーバーコンポーネントから直接使うとエラーになります。
回避策は、自分のコードで「use client」を付けた薄いラッパーを作り、そこから再エクスポートすることです。UIライブラリを多用する構成なら、ラッパー置き場をあらかじめ決めておくと散らかりません。コンポーネントカタログを併用している現場では「Storybookとは|UIコンポーネント開発の基本・導入メリットを解説」の運用も合わせて検討する価値があります。Reactの定番UIライブラリの選定は「Material UI(MUI)とは|Reactの定番UIライブラリ・使い方・案件動向」で整理しています。
5. キャッシュと再検証の挙動を読み違える
RSCは、ビルド時実行とリクエスト時実行のどちらにもなります。加えてフレームワーク側のキャッシュ層が重なります。「更新したのに古い内容が出る」という問い合わせは、ここが原因になりがちです。
参画直後に確認すべきは、どの画面がビルド時に固定され、どの画面がリクエストごとに動いているかの一覧です。フレームワークのバージョンによってキャッシュの既定値は変わるため、プロジェクトの公式ドキュメントとバージョンを合わせて確認してください。
RSCを採用すべきか、見送るべきか
判断軸は「サーバーで完結させたい処理の量」と「移行コスト」です。以下は観測ベースの整理で、プロジェクト条件によって結論は変わります。
向いているケース
SEOが売上に直結するメディア・EC・コーポレートサイト:初期表示を軽くしたい要求と相性がよい
ダッシュボード型のSaaS:データ取得が多く、取得用APIを減らせる効果が出やすい
CMS連携の静的ページが多いサイト:ビルド時実行でCDN配信に寄せられる
見送る・急がないケース
稼働中のSPA(Viteなどで構築したクライアント専用アプリ):RSCの導入はルーティングとビルド構成の変更を伴うため、効果の見積もりなしに着手すると割に合わない
社内向けの管理画面で初期表示要件が緩い案件:クライアント専用構成のままでも要件を満たせることが多い
チームにApp Routerの運用経験がない状態での短納期案件:境界設計のレビュー体制がないと、クライアント化の侵食が起きやすい
静的サイト寄りの要件なら「Astroとは|静的サイトジェネレーターの特徴・Next.jsとの違い・将来性を解説」、ルーティング中心の構成なら「Remixとは|特徴・Next.jsとの違い・React Router v7統合を解説」も比較対象になります。チーム分割の都合でフロントを分けたい場合は「マイクロフロントエンドとは|分割方式・採用判断・運用コストと見送る基準」で採否の基準を扱っています。
執筆時点の対応状況
RSCはReact本体だけでは利用できません。フレームワークまたはバンドラー側の対応が前提です。以下は2026年10月12日に各公式ドキュメントを確認した時点の状況です。この領域は更新が速いため、導入前に必ず現行版を見てください。
環境 | 確認時点の状況 |
|---|---|
Next.js App Router | 公式ドキュメントでサーバーコンポーネントが既定として案内されている |
React Router | 公式ドキュメントに実験的サポートと明記。マイナー/パッチで破壊的変更の可能性あり |
Vite | React Router経由のテンプレートで@vitejs/plugin-rscを使う構成が案内されている |
React本体の最新安定版は公式のVersionsページで確認できます。バージョン依存の挙動は、参画時に公式リリースノートで現行版を確認してください。
デプロイ先の選定でVercelを前提にする案件も多いため、「Vercelとは?特徴・Next.js連携・料金・案件動向をフリーランス視点で解説」も合わせて確認しておくと要件のすり合わせが早くなります。
フリーランスエンジニアがRSC案件で確認すること
RSCは「書ける/書けない」よりも設計判断を任せられるかで評価されます。参画前後で押さえるべき点を整理します。
参画前に確認する5項目
App RouterかPages Routerか、併存しているか(併存案件は境界の例外が増える)
キャッシュ戦略の方針が文書化されているか(口伝だけの現場は手戻りが多い)
デプロイ先がVercel前提か、自前のNode環境かコンテナか
「use client」の付与ルールがレビュー基準として存在するか
移行途中かどうか。移行案件なら、1スプリントで何画面ずつ移すかの計画があるか
この5項目は面談で聞けます。答えが曖昧な案件は、実装そのものより設計の整備から入る前提で工数を見ておくのが無難です。
スキル評価と単価の考え方
RSC単体での単価データは公開案件からは切り出しにくく、実務ではNext.jsやReactのスキルセットとして評価されるのが一般的です。境界設計やキャッシュ設計まで任せられる人は、実装中心の募集より高く評価される傾向があります。
具体的なレンジは「Next.js案件の単価相場|必要スキル・経験別レンジと探し方」「Reactフリーランス単価相場|案件動向・スキル別レンジ・獲得の実務」で整理しています。単価を体系的に上げる考え方は「フリーランスエンジニアの単価相場と単価の上げ方」が参考になります。
自分の経験でどのくらいの単価を狙えるか確認したい場合は、無料のフリーランスエンジニア単価診断で市場単価の目安を把握できます。案件一覧でReact・Next.jsの募集要件を見比べておくと、どこまでの設計スキルが求められているかの肌感もつかめます。
学習と移行の進め方
最短ルートは、対応フレームワークのテンプレートで動くものを作ることです。順序の目安を示します。
App Routerの最小構成で、サーバーコンポーネントから直接DBまたはAPIを読む画面を1つ作る
そこへインタラクティブな要素を1つ足し、「use client」を末端のファイルだけに付ける
境界に渡すpropsを意図的に壊してみる(関数やクラスインスタンスを渡す)。エラーの出方を体験しておく
childrenスロットでサーバーコンポーネントを差し込むパターンを試す
Server Functionsで更新処理を1本書き、認可チェックを入れる
既存アプリの移行は、ルート単位で1〜2画面ずつ進めるのが現実的です。一度に広げると、境界の設計ミスがどこから来ているか追えなくなります。
実践チェックリスト
公開前・レビュー前に確認する項目です。このまま使えるようにまとめました。
「use client」は末端のインタラクティブなファイルにのみ付いているか
レイアウトやページに不要な「use client」が残っていないか
境界に渡すpropsはシリアライズ可能な型に限定されているか(関数・クラスインスタンスなし)
ORMのモデルをプレーンオブジェクトへ変換してから渡しているか
サーバー専用モジュールにserver-onlyのimportを入れているか
公開してよい環境変数だけが公開用の接頭辞を持っているか
Context Providerはツリーの深い位置に置かれているか
Server Functionsに入力検証と認可チェックが入っているか
どの画面がビルド時固定で、どの画面がリクエストごとの実行かを一覧化したか
サードパーティUIのラッパーの置き場所がチームで統一されているか
まとめ
RSCは「サーバーで実行するコンポーネント」を手に入れる仕組みであり、習得の中心は文法ではなく境界の設計です。
RSCはサーバーのみで実行され、クライアントのJSバンドルに含まれない
目印を付けるのはクライアント側。「use client」はモジュール依存ツリーに境界を作る
描画結果はRSCペイロードという中間形式になり、そこからHTMLが作られる
境界に渡せるpropsはシリアライズ可能な型に限られる。関数とクラスインスタンスで落ちやすい
Server Functionsは公開エンドポイント。入力検証と認可チェックを必ず入れる
採用判断は「サーバーで完結させたい処理の量」と「移行コスト」で決める
素のReactでは使えず、対応フレームワーク・バンドラーが前提になる
次のアクションとしては、App Routerの最小構成で画面を1つ作り、「use client」を末端だけに付ける体験を済ませてしまうのが早いです。そのうえで、参画前の5項目を面談で確認できるようにしておくと、設計の整備コストを見落とさずに案件を選べます。
参照した一次情報は以下です。
よくある質問
RSCとSSRはどちらを選ぶものですか
選択関係にありません。RSCはコンポーネントの実行環境、SSRはHTML生成の工程です。App RouterではRSCペイロードを経由してHTMLが作られるため、両方が同時に働いています。
サーバーコンポーネントに「use server」と書けばよいのですか
違います。「use server」はServer Functions用のディレクティブです。サーバーコンポーネントを示す専用の書き方はなく、App Routerでは何も書かなければサーバー側になります。
useStateをサーバーコンポーネントで使うとどうなりますか
エラーになります。状態を持たせたい部分を切り出し、そのファイルに「use client」を付けてください。切り出した側へ初期値をpropsで渡す形が一般的です。
クライアントコンポーネントの中にサーバーコンポーネントは置けますか
importはできませんが、childrenなどpropsとして渡す形なら置けます。渡された側はサーバーで描画され、結果がRSCペイロードに載ります。
サーバーコンポーネントからクライアントへ関数を渡せませんか
通常の関数は渡せません。サーバーで実行したい処理なら「use server」を付けたServer Functionsにすると渡せます。その場合は公開エンドポイントになるため、認可チェックが必要です。
既存のVite + React構成にRSCを後から足せますか
React Router経由でViteプラグインを使う構成が案内されていますが、公式ドキュメント上は実験的扱いです。稼働中のプロダクトに入れる判断は、破壊的変更のリスクを織り込んでから行ってください。
RSCにすればCore Web Vitalsは必ず改善しますか
必ずではありません。クライアントへ送るJSが減れば有利に働きますが、サーバー側の応答が遅ければ初期表示は改善しません。計測してボトルネックを特定してからの判断になります。
データ取得はすべてサーバーコンポーネントに寄せるべきですか
初期表示に必要なデータはサーバー側が向きます。一方で、ユーザー操作に応じて細かく更新する部分はクライアント側で取得したほうが素直です。両方を使い分ける前提で設計してください。
サーバーコンポーネントのテストはどう書きますか
async関数として返り値を検証する方法が取りやすい一方、ツール側の対応状況に依存します。境界の内側のロジックを純関数へ切り出し、そこを単体テストの対象にすると取り回しが楽になります。
RSCが使えないと案件に通りませんか
React・Next.js案件のすべてがApp Router前提ではありません。Pages Routerや、Vite構成のSPAの案件も募集されています。ただしApp Router案件の面談では境界設計の考え方を問われることが多く、説明できると評価につながります。
学習にはどのくらい時間を見ておけばよいですか
一概には言えませんが、前述の5ステップを手元で一通り動かすだけなら数日単位で足ります。難しいのは文法ではなく、キャッシュと境界の設計判断です。実務の画面を何枚か設計してみるのが結局は早道です。
