👀

Next.jsの「コンポーネントの種類」と「レンダリング方式」は別の話

に公開

最初に整理:2つの異なる概念

Next.jsを学習していると、こんな用語がたくさん出てきます:

  • Server Component / Client Component
  • SSR / CSR / SSG

これらは全部「サーバー」や「クライアント」という言葉が入っているので、同じような概念に見えますよね。でも実は、まったく別の話なんです。

コンポーネントの種類(RSC/RCC) = 「どこでコードが実行されるか」
レンダリング方式(SSR/CSR/SSG) = 「いつHTMLが作られるか」

この2つは独立した概念で、組み合わせて使うものです。

コンポーネントの種類を理解する

Server Component(サーバーコンポーネント)

// app/products/page.tsx
export default async function ProductsPage() {
  // このコードはサーバーでのみ実行される
  const products = await fetch('https://api.example.com/products');
  
  return (
    <div>
      <h1>商品一覧</h1>
      {products.map(product => (
        <div key={product.id}>{product.name}</div>
      ))}
    </div>
  );
}

特徴: サーバーでのみ実行、データベース直接アクセス可、JavaScriptバンドルに含まれない

Client Component(クライアントコンポーネント)

// components/LikeButton.tsx
"use client"
import { useState } from 'react';

export default function LikeButton() {
  // このコードはブラウザでも実行される
  const [liked, setLiked] = useState(false);
  
  return (
    <button onClick={() => setLiked(!liked)}>
      {liked ? '❤️ いいね済み' : '🤍 いいね'}
    </button>
  );
}

特徴: ブラウザで実行、React Hooks使用可、JavaScriptバンドルに含まれる

レンダリング方式を理解する

  • SSR(Server-Side Rendering): リクエストのたびにサーバーでHTMLを作る
  • SSG(Static Site Generation): ビルド時にあらかじめHTMLを作っておく
  • CSR(Client-Side Rendering): ブラウザでHTMLを作る

よくある混乱:「Server Component = SSR」ではない

多くの人がこう思いがちです:

❌ 間違った理解
Server Component → サーバーでHTML作成 → SSR
Client Component → ブラウザでHTML作成 → CSR

でも実際は:

✅ 理論的には正しい組み合わせ
Server Component + SSR → サーバーコンポーネントをリクエスト時にHTML化
Server Component + SSG → サーバーコンポーネントをビルド時にHTML化
Client Component + SSR → クライアントコンポーネントをリクエスト時にHTML化
Client Component + CSR → クライアントコンポーネントをブラウザでHTML化

Next.jsの実際のデフォルト動作

ただし、Next.js App Routerでは、可能な限り事前にHTML化することを優先します:

📋 Next.jsのデフォルト動作
Server Component → 自動的に静的最適化(SSG的な動作)
Client Component → デフォルトでSSR(初回はサーバーでHTML化)

つまり、何も指定しなければ、ほとんどのコンテンツが事前にHTML化されます。

実際の組み合わせ例

パターン1:Server Component(デフォルト = 静的最適化)

// app/blog/page.tsx
export default async function BlogPage() {
  // デフォルトで静的最適化される
  const posts = await getPosts();
  
  return (
    <div>
      <h1>ブログ</h1>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.excerpt}</p>
        </article>
      ))}
    </div>
  );
}

結果: 高速表示、SEOに優しい、サーバー負荷軽減

パターン2:Client Component(デフォルト = SSR + ハイドレーション)

// components/SearchForm.tsx
"use client"
import { useState } from 'react';

export default function SearchForm() {
  const [query, setQuery] = useState('');
  
  return (
    <form>
      <input 
        value={query} 
        onChange={(e) => setQuery(e.target.value)}
        placeholder="検索..."
      />
      <button type="submit">検索</button>
    </form>
  );
}

結果: 最初からフォームが表示され、その後インタラクティブになる

パターン3:Client Component + 明示的CSR

import dynamic from 'next/dynamic';

const ClientOnlyChart = dynamic(
  () => import('./Chart'),
  { ssr: false } // 明示的にSSRを無効化
);

export default function DashboardPage() {
  return (
    <div>
      <h1>ダッシュボード</h1>
      <ClientOnlyChart />
    </div>
  );
}

結果: タイトルは即座に表示、チャートは少し遅れて表示

実践的な判断基準

Server Componentを選ぶとき

  • データベースアクセスが必要
  • SEOが重要
  • ユーザーインタラクションが不要

Client Componentを選ぶとき

  • useState、useEffectが必要
  • ブラウザAPIを使用
  • ユーザーインタラクションが必要

CSRを明示的に選ぶとき

  • SEOが不要(管理画面など)
  • 明示的にssr: falseを指定する必要がある

組み合わせの実例

// app/shop/page.tsx
export default async function ShopPage() {
  // Server Component + 静的最適化(デフォルト)
  const products = await getProducts();
  
  return (
    <div>
      <h1>オンラインショップ</h1>
      <ProductList products={products} />        {/* Server Component */}
      <SearchForm />                             {/* Client Component(SSR) */}
      <ShoppingCart />                           {/* Client Component(CSR) */}
    </div>
  );
}

この例では:

  • 商品リスト:SEOのためServer Component(静的最適化)
  • 検索フォーム:インタラクションが必要なのでClient Component(デフォルトでSSR)
  • ショッピングカート:ユーザー専用データなので明示的にCSR化

まとめ

Next.jsの「コンポーネントの種類」と「レンダリング方式」は別々の概念です:

コンポーネントの種類(どこで実行?)

  • Server Component:サーバーでのみ実行
  • Client Component:ブラウザで実行(サーバーでも実行される場合あり)

レンダリング方式(いつHTML生成?)

  • SSR:リクエスト時
  • SSG:ビルド時
  • CSR:ブラウザで

Next.jsのデフォルト動作:

  • Server Component → 静的最適化(SSG的)
  • Client Component → SSR + ハイドレーション
  • CSRは明示的指定が必要(ssr: false

「どこで実行するか」と「いつHTML化するか」を分けて考え、Next.jsのデフォルト動作(可能な限り事前HTML化)を理解すると使いやすくなります。実際にコードを書きながら、それぞれの特徴を体感してみてください!


参考資料

Discussion