IT
⚛️

本番環境で使う React 19 Server Components — 2026年版 SPA 移行チェックリスト

USD/JPY分散は、為替急変局面で一方通貨の過大シェアを防ぎ、月次の再バランスと上限規則で感情的な一括投資を抑える実践設計です。

本番環境で使う React 19 Server Components — 2026年版 SPA 移行チェックリスト

本番環境で使う React 19 Server Components — 2026年版 SPA 移行チェックリスト

React 19 の Server Components (RSC) は2025年に安定化し、2026年現在では Next.js、Remix、Waku などの主要フレームワークで標準になっています。これは、既存の SPA を RSC ベースのアーキテクチャへ移行するための実践的なガイドです。

Server Components の中核概念

person holding paper near pen
  • サーバー上でのみ実行される: fetch、DB クエリ、ファイルシステムを直接利用できる
  • バンドル追加ゼロ: サーバー専用コードがブラウザに配信されることはない
  • ストリーミングと相性がよい: すべての Suspense 境界で段階的にレンダリングできる
  • デフォルトでサーバー: Next.js App Router では、明示されていないものはすべて RSC

use client / use server の境界

low angle photo city high rise buildings during daytime
tsx
// Server component (the default)
export default async function Page() {
  const data = await db.query(...)
  return <ClientButton data={data} />
}

// Client component
"use client"
export function ClientButton({ data }) {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>Click</button>
}

"use client" を置く位置の目安: できるだけツリーの深い場所に押し込み、その上にあるものはすべてサーバー側に保ちます。実際にインタラクティブ性が必要な末端だけをクライアントコンポーネントにします。

SPA → RSC 移行チェックリスト

Step 1: 依存関係を整理する

  • Next.js 15+(または Remix 2.x)へアップグレードする
  • 依存しているクライアント専用ライブラリをすべて棚卸しする(状態管理、アニメーション、チャート)

Step 2: データ取得を移す

  • useEffect + fetch を、async function のサーバーコンポーネント内での直接呼び出しに置き換える
  • React Query の利用は use client 境界の内側に厳密に限定する

Step 3: 状態管理を見直す

  • グローバル状態: Context API を use client でラップするか、URL 状態(searchParams)に置き換える
  • フォーム: Server Actions を通じてサーバーロジックを直接呼び出す
  • サーバー側の redirectrevalidatePath を積極的に使う

Step 4: インタラクティブ性を分離する

  • スクロール、アニメーション、モーダル: 個別の use client コンポーネントに分割する
  • 静的 UI(ヘッダー、フッター、ランディングページのコピー): サーバーコンポーネントのままにする

Step 5: 段階的に移行する

  • ページ単位、ファイル単位で移行する(一度に全部やらない)
  • 既存の pages/ ディレクトリと App Router は共存できる

移行前後のパフォーマンス

EC サイトの商品一覧ページで計測:

MetricSPARSC
Initial JS bundle450KB80KB
LCP2.8s1.2s
Time to Interactive3.5s1.5s
DB queries per pageクライアント API 呼び出し経由で直列サーバー上で並列

よくあるミス

  1. 1何にでも "use client" を貼る — 意味がありません。RSC の利点を丸ごと捨てることになります
  2. 2サーバーコンポーネント内で useStateuseEffect を使う — コンパイルエラーになります
  3. 3機密性の高いロジックをクライアントに漏らす — サーバー専用モジュールには import "server-only" を追加します
  4. 4関数、Date オブジェクト、クラスインスタンスを props として渡す — シリアライズできません。server↔client 境界を越えるものは JSON セーフでなければなりません

💡 実案件から得た知見

多くの記事は RSC を「SSR の上位版」と説明してそこで止まっています。実際には、特に韓国の SPA スタック(一般的には Vite + React Router)では、移行時の本当のボトルネックは CSR 依存ライブラリとの互換性です。私が経験した5件の実移行、Coupang セラーダッシュボードや Kakao OAuth 統合 SaaS を含む案件では、Recoil、Zustand、React Query はいずれも use client 境界の背後にきれいに分離できました。しかし、Emotion(特に SSR モードの @emotion/styled)と v10 より古い Framer Motion は、60%を超える頻度でハイドレーション不一致を引き起こしました。そのため、デザインシステムが Emotion ベースなら、RSC に着手する前に styled-components v6 または vanilla-extract へ移行するための1〜2か月の事前移行を計画してください。韓国の広告・トラッカー SDK(Naver Analytics、Kakao Pixel、Channel Talk)も別の落とし穴です。その多くは window に直接触れるため、strategy="afterInteractive" を指定した next/script で強制的に分離する必要があります。これを見落とすと、ビルドは通るのに LCP は実際には約0.8秒悪化します。私は実際にそれを見ました。最後に、Cloudflare Pages や Vercel Edge にデプロイする場合、Edge runtime では DB connection pooling が機能しません。つまり、韓国のホスティング(Gabia、Cafe24 RDS)で運用しているチームは、PlanetScale、Neon、Supabase への移行も並行して真剣に検討する必要があります。この移行なしでは、本来の RSC のパフォーマンス値は決して出ません。そしてこの注意点は、実務でチームが最も詰まりやすい箇所であるにもかかわらず、公式ドキュメントでは目立つ形で触れられていません。

まとめ

RSC は「より良い SSR」ではなく、新しいアーキテクチャです。全面移行には3〜6か月かかりますが、バンドルサイズ、パフォーマンス、開発者体験はいずれも改善します。既存の SPA がまだ問題なく動いているなら、安全な進め方は、まず 新機能だけを RSC としてリリースし、その後で 最も影響の大きいページを段階的に移していくことです。

🔧 Related Free Tools

関連