Blog 一覧に戻る
ReactRSCパフォーマンス

React Server Components 深掘り — クライアントとサーバーの境界を理解する

RSC はレンダリングモデルを根本から変えました。Server Component・Client Component・Shared Component の使い分けや、データフェッチ戦略、バンドルサイズへの影響を実例をもとに整理します。

React Server Components とは

React Server Components(RSC)は、コンポーネントをサーバー側でレンダリングし、その結果をクライアントに送る新しいアーキテクチャです。従来の SSR とは異なり、クライアントに JavaScript を送らずにコンポーネントを描画できます。

3種類のコンポーネント

Server Component(デフォルト)

// app/blog/page.tsx(Server Component)
export default async function BlogPage() {
  // サーバー上で直接DBアクセス可能
  const posts = await db.post.findMany()
  return <PostList posts={posts} />
}

Client Component

'use client'
import { useState } from 'react'

export function LikeButton({ postId }: { postId: string }) {
  const [liked, setLiked] = useState(false)
  return (
    <button onClick={() => setLiked(l => !l)}>
      {liked ? '❤️' : '🤍'}
    </button>
  )
}

Shared Component

どちらの環境でも動作できる「境界を意識した」コンポーネントです。hooks やブラウザ API を使わない純粋な UI コンポーネントがこれに当たります。

データフェッチ戦略

RSC ではコンポーネントを async にするだけでデータフェッチが書けます。

// ウォーターフォールを避けるため並列フェッチ
export default async function Dashboard() {
  const [user, stats] = await Promise.all([
    fetchUser(),
    fetchStats(),
  ])
  return (
    <>
      <UserCard user={user} />
      <StatsPanel stats={stats} />
    </>
  )
}

よくある間違い

Server Component に Client Component を import するのは OK

// Server Component
import { ClientButton } from './ClientButton' // ✅

export default function Page() {
  return <ClientButton />
}

Client Component から Server Component を import するのは NG

'use client'
import { ServerComponent } from './ServerComponent' // ❌ エラー

children として渡すのは OK

'use client'
export function ClientWrapper({ children }: { children: React.ReactNode }) {
  return <div>{children}</div>
}

// Server Component 側
import { ClientWrapper } from './ClientWrapper'
import { ServerContent } from './ServerContent'

export default function Page() {
  return (
    <ClientWrapper>
      <ServerContent /> {/* ✅ children として渡すのはOK */}
    </ClientWrapper>
  )
}

バンドルサイズへの影響

Server Component はクライアントの JS バンドルに含まれません。重いライブラリ(markdown パーサー、日付処理など)をサーバー側に閉じ込めることで、クライアントのバンドルサイズを大幅に削減できます。

まとめ

RSC の核心は「どこで実行するかを明示的に設計すること」です。デフォルトでサーバーで動き、インタラクティブな部分だけクライアントに委ねるという思想は、パフォーマンスと開発体験の両立を実現しています。