先に要点
- React Server Components(RSC) は、サーバで実行され、結果(HTML / シリアライズ済みツリー)だけがクライアントに届く 新種のコンポーネント。`使った分のクライアント JS が増えない』 が最大の価値。
- サーバ専用なので、DB / 内部 API / ファイルシステム / 秘密情報を直接読める 一方、` useState』 `useEffect』 `onClick』 などの `状態とブラウザイベント』 系は使えない。
- インタラクション要素は ` Client Components』(`use client』 ディレクティブを書いたファイル) に切り出す。RSC は `データを取って木を組み立てる』、Client Components は `動かす』 という役割分担。
- 事実上の本命採用先は Next.js App Router。Vercel が AI 時代に存在感を増す流れと同じく、` バンドル削減 + ストリーミング + サーバ集約』 という方向に Web 全体が動いている、その代表格。
Next.js の App Router に切り替えたら use client』 って書かないとエラーが出るようになった』 RSC ってよく聞くけど Server Side Rendering とどう違うの? データ取得は useEffect + fetch』 でいいのか、それとも async コンポーネント』 で書くのか分からない』 ── React と Next.js が一気に進化したことで、書き方の前提』 が大きく変わったのが2024年以降の状況です。
ざっくり言うと、Server Components は サーバで動かす React コンポーネント』</strong> で、これまでの React コンポーネント』 とは 動く場所と使える機能 が違います。
サーバで動くから速い』 という単純な話ではなく、<strong> クライアントに JS を送らない』 という選択肢を React 自身に持たせた、というのが本質的な変化 です。
この記事では、2026年5月時点の React 19 / Next.js 15 系をベースに、RSC の仕組み・Client Components との境界・データ取得のコード・落とし穴・採用判断 を、`なんとなく書いていたが理屈が掴めていない』 レベルから一段上に行けるよう整理します。
まず2行で言うと
長文を読む前に、結論だけ先に固定しておきます。
RSC は `サーバで動く React コンポーネント』
サーバで JSX を実行 → 結果をクライアントに送る。クライアント側 JS バンドルには出ない。DB や秘密情報を直接読める 代わりに、状態 / イベント / hooks は使えない。
Client Components は `ブラウザで動く React コンポーネント』
`use client』 を書いたファイル。` useState』 `onClick』 `useEffect』 等の動的要素が使える。バンドルにも乗る。
RSC が Client を子として取り込める
RSC の中に Client Components を埋め込めるが、` Client Components の子は基本 Client 側』。境界が `ツリーの上から下』 に伝播する。
RSC = SSR の新版』 ではなく、SSR の世界に `クライアント JS を載せないコンポーネント』 という新しいピースを追加したもの』 と捉えるのが正確です。
なぜ RSC が必要になったか
`React と Next.js は何が足りなくて RSC を導入したのか』 を見ると、設計意図が分かります。
② データ取得の二段構え
` getServerSideProps』 → コンポーネントに props で渡す、という別レイヤーが必要だった。`コンポーネントから直接 DB を呼びたい』 が叶わなかった。
④ ストリーミングを活かしたい
サーバから `準備できた部分から順番に流す』 ことで体感速度を上げたい。RSC は ツリー単位でのストリーミング と相性が良い。
つまり ` クライアントに送らないでいい部分はサーバに留めたい』 という最適化を、コンポーネントモデルそのものに組み込んだ のが RSC です。
サーバとクライアント、それぞれで何ができて何ができないか
具体的な利用可否を表で押さえます。
| 機能 | Server Components | Client Components |
|---|---|---|
| JSX を書く | ○ | ○ |
| async / await を直接書く | ○(`export default async function ...』) | ×(基本) |
| DB クライアントを呼ぶ | ○(Prisma / Drizzle / SQL 直接) | × |
| 環境変数(秘密含む)を読む | ○(サーバから) | ×(`NEXT_PUBLIC_』 接頭辞のみ) |
| useState / useEffect / hooks | × | ○ |
| onClick / onChange など | × | ○ |
| Context を使う | △(取得は不可、子として埋めるのは可) | ○ |
| クライアント JS への影響 | なし(送らない) | あり(バンドルに乗る) |
どの機能はどっち側か』 を意識しないと、useState が使えない』 event handler は使えない』 系のエラーで詰まります。 RSC 時代の React は、<strong> この境界を意識すること』 が新しい必須スキル です。
`use client』 ディレクティブとは
Next.js / React は、ファイルの先頭に 'use client';』 と書くことで、このファイル(とその関数 / コンポーネント)はクライアント側』 と明示します。
'use client';
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}
このファイルからエクスポートされるものは、それを使う側に Client 境界を引きます。
RSC からは普通に import』 して埋め込めますが、<strong> use client』 を書いたファイルとその先』 はバンドルに乗る、と理解するのがコツです。
境界の伝播
`use client』 を書いたファイルから `import』 した別ファイルは、自動的に Client 側として扱われる。`境界は上から下に流れる』 のが原則。
RSC を Client から呼ぶには
Client Components の 子として RSC を埋め込むには、`props.children』 として渡す形にする。`Client が直接 RSC を import』 はできない。
なるべく境界は下に
` 上のほうから use client』 にすると、丸ごとクライアントに送る羽目になる。`小さな葉の部分だけ Client』 が理想形。
秘密情報の漏洩防止
Client Components で `process.env.SECRET』 のような形で書くと、ビルド時に警告 / エラーになる。`サーバでしか読まない』 ことが構造的に守られる。
use client』 は <strong> ここから先はクライアントですよ』 の境界線 であって、`このファイルをクライアントに送る』 だけのスイッチではない、というのが正確な理解です。
Next.js App Router での書き方
実際の Next.js App Router で `データを取って表示する RSC』 はどう書くのか、コード例で確認します。
// app/users/[id]/page.tsx
import { db } from '@/lib/db';
import { LikeButton } from './LikeButton';
export default async function UserPage({ params }: { params: { id: string } }) {
const user = await db.user.findUnique({ where: { id: params.id } });
if (!user) return <div>Not found</div>;
return (
<div>
<h1>{user.name}</h1>
<p>{user.bio}</p>
<LikeButton userId={user.id} initialLikes={user.likes} />
</div>
);
}
// app/users/[id]/LikeButton.tsx
'use client';
import { useState } from 'react';
export function LikeButton({ userId, initialLikes }: { userId: string; initialLikes: number }) {
const [likes, setLikes] = useState(initialLikes);
return (
<button onClick={() => setLikes(l => l + 1)}>♥ {likes}</button>
);
}
境界の引き方
`LikeButton』 だけ Client にして、それ以外の本体は RSC のまま。` バンドルされるのはボタンだけ』 という設計が自然に書ける。
セキュリティの安心感
` db.user.findUnique』 の呼び出しがクライアントに漏れる心配がない。`サーバの中だけで完結する』 と確信できる。
テストのしやすさ
RSC は基本 `関数として呼ぶ』 単位なので、`単体テストでは引数を渡して結果の JSX を検証』 という形でテストしやすい。
データ取得用のhooks がいらなくなった』 のが、App Router の体験を大きく変えた点です。 [tRPC](/articles/what-is-trpc-typesafe-api) と組み合わせる場合も、procedure をサーバコンポーネントから直接呼ぶ』 のような構成が普通に書けます。
データ取得とキャッシュ
App Router の RSC は、`fetch を直接書く』 だけで Next.js が裏でキャッシュを管理してくれます。
const res = await fetch('https://api.example.com/posts', {
next: { revalidate: 60 }, // 60秒キャッシュ
});
デフォルト挙動
Next.js 15 系では、`fetch』 は `force-cache』 ではなく `no-store』 寄りがデフォルトに変更された。`常に最新を取る』 を基本にし、必要な場面で明示的にキャッシュする方針。
時間ベース無効化
`{ next: { revalidate: 60 } }』 のように指定すると、`60秒間はキャッシュを返す』 = ISR(Incremental Static Regeneration)的な動作になる。
タグベース無効化
`{ next: { tags: ['posts'] } }』 と書き、`revalidateTag('posts')』 でまとめて無効化。`投稿があったときだけキャッシュをクリアしたい』 ユースケースに合う。
このキャッシュ設計と Vercel の請求が高くなる原因 は密接に関係します。
revalidate を小さくしすぎる』 と関数実行や帯域がそのまま課金に響くので、本当に短くする必要があるか』 を毎回考えるのが大事です。
RSC のよくある詰まりどころ
実際に開発していてよく出会う罠を整理しておきます。
①「useState を Server Components で使えない」エラー
そのファイルの先頭に `'use client';』 を書くか、`useState を使う部分だけ Client コンポーネントに切り出す』 のが正解。`コンポーネントごと Client』 にすると、無駄にバンドルが膨らむ。
② Client Component の子に async コンポーネントを書きたい
Client → Server の direct な import はできない。`props.children として上から渡す』 形に書き換える。`composition で境界を越える』 が React チームの推奨方針。
③ Context をどこに置くか
Context Provider は Client Component。RSC 内で `useContext』 はできない。`Provider を Client、子は RSC』 という配置が普通に書ける。
④ クライアント側でだけ動くライブラリ
` window』 を直接触るライブラリは、当然 Client Component でだけ動く。`use client』 を書いたファイルからのみ import するのが安全。
⑤ async コンポーネントのテストの書き方
RSC は `関数自身が Promise を返す』 ので、テストでは `await Component({...})』 のように呼んで結果の JSX を検証する。従来の `render()』 ベースのテストとは作法が違う。
⑥ 古いライブラリの互換性
`use client』 のないままサーバで実行できない依存(`window.matchMedia』 等を import 時に触る古い UI ライブラリ)はそのままだと動かない。`use client』 でラップするか、`next/dynamic』 で SSR off にする回避策が必要。
境界をどこに引くか』 を意識するだけで、ほとんどの問題は解決します。 慣れるまではエラーが多めですが、慣れてくると <strong> 自然と Client は葉先だけ』 という配置に向かう ようになります。
採用判断の軸
`RSC を採用すべきか』 の判断材料を整理しておきます。
向いている案件
① 中〜大規模 Next.js プロジェクト、② コンテンツ + 一部インタラクション、③ クライアント JS の重さがすでに問題、④ サーバとフロントを TS で1人/小チームが書く構成。
急がなくていい案件
① まだ動いている Pages Router の小規模アプリ、② SSG が中心で十分早いブログ、③ RSC 非対応のライブラリに強く依存する案件。
他フレームワークでの状況
Remix(現 React Router)、Waku、TanStack Start などでも RSC サポートが進行中。`Next.js 専用』 ではないことを覚えておくと、将来の選択肢が広がる。
学習時間の目安
すでに React に慣れている人なら、`境界の感覚』 を掴むのに 2 日〜1 週間程度。`use client』 を脳内で `読む』 練習を意識的にすると速い。
新規プロジェクトで Next.js なら、まず App Router + RSC で始めて、必要に応じて use client』 を貼る』 が、2026年現在の現実的な標準です。
v0 で UI を作る ような AI 連携の文脈でも、`生成された UI は Client、データ取得は Server』 という配置が自然に決まりやすくなります。
AI 時代の RSC
AI を組み込んだアプリで RSC が嬉しい場面はいくつかあります。
ストリーミング応答
AI の応答を サーバで受け取って、必要な単位でクライアントに送る。RSC + Server Actions + Suspense と組み合わせると、`AI が出してきたものを順次表示する UI』 が綺麗に書ける。
バンドルサイズの維持
AI 関連のライブラリは大きくなりがち。`サーバだけで使う AI ライブラリはバンドルに乗らない』 のが、ユーザー体感速度に効く。
`AI が出力 → サーバが整形 → 必要な部分だけ Client で動かす』 という現代的な構造が、RSC によって自然に書けるようになったのが大きな変化です。
React Server Components に関するよくある質問
Q. RSC は SSR とどう違うのですか?
A. SSR は 初回 HTML をサーバで作る + クライアント側 JS も送る』、<strong>RSC</strong> は クライアントに JS を送らない種類のコンポーネント』 です。並べて使うもので、`SSR + RSC』 が App Router の標準的な構成になっています。
Q. すべてを RSC にすべきですか?
A. いいえ。動かす部分(ボタン、フォーム、ドラッグ操作など)』 はどうしても Client Components が必要です。<strong> 葉の部分だけ Client にして、構造は RSC』 という設計が一番素直に書けます。
Q. RSC からクライアントに `props』 で何でも渡せますか?
A. シリアライズ可能なものに限定されます。関数 / クラスインスタンス / DOM ノード / Promise(条件付き) は基本的には渡せません。`値や JSX』 は渡せます。
Q. ローカルストレージや Cookie は RSC で扱えますか?
A. localStorage はクライアント専用 なので RSC では触れません。Cookie はサーバで cookies()』 API を使えば読めます</strong>。これにより ログイン中ユーザーで分岐』 のような処理を RSC で完結できます。
Q. RSC でエラーをハンドリングするには?
A. error.tsx』 を App Router のルートセグメントに置くと、その配下でエラーが起きたときに表示される Client Component が動きます。try / catch + JSX』 を直接書くことも可能です。
Q. RSC の本番運用は安全ですか?
A. 2024年〜2025年で大幅に成熟しました。Next.js を本番採用している企業の多くが App Router に移行済みで、本番運用上の問題は概ね小さい 状態です。とはいえ、`古いライブラリの非互換』 等は残るので、移行時には依存の点検が必要です。
Q. RSC は将来的に標準になりますか?
A. React の中核機能としてすでに 標準』</strong> です。React 19 でリリースされ、Remix(React Router) / Waku など Next.js 以外のフレームワークでも採用が進んでいます。一過性のトレンド』 ではなく `React の進化方向そのもの』 と捉えるのが現実的です。
参考リンク
- React 公式: Server Components
- Next.js: App Router 公式
- Next.js: Server and Client Components
- React 公式: `use client』
- Vercel Blog: Understanding React Server Components
- Remix(React Router): 公式