Next.jsのClientコンポーネントなのにSSRされてる?を理解する

Next.jsのClientコンポーネントなのにSSRされてる?を理解する

2025/04/10

最近、Next.jsのApp Routerで開発を進めている中で、ある挙動に違和感を持った方もいるのではないでしょうか?

'use client' って書いてるのに、なんかサーバーでレンダリングされてるっぽい……?」

実はこれ、Next.jsのApp RouterではクライアントコンポーネントでもHTMLはサーバーで生成されるという仕組みによるものです。

今回はこの挙動を整理し、「クライアントコンポーネント=CSR(Client Side Rendering)」と思い込んでいると見誤りやすい点を、実例とともにわかりやすく解説します。


Clientコンポーネントとは?

まず基本を整理します。

  • 'use client' が先頭に書かれたファイルはクライアントコンポーネントになります。

  • Reactのhooks(useState, useEffect など)やイベントハンドラ(onClick など)を使う場合、'use client' が必要です。

  • ここで誤解されがちなのが、クライアントコンポーネント=CSRになるという思い込みです。

実際には、App Routerでの挙動はそれとは異なります。


App Routerの基本:まずはHTMLがサーバーで生成される

Next.js 13以降のapp/ディレクトリでは、ページの初期HTMLは常にサーバーで生成(SSRまたはSSG)されます。

これにはクライアントコンポーネントも含まれており、サーバーでHTMLを生成した後にクライアント側でhydrate(復元)される流れになります。

つまり:

'use client' があっても、HTML自体はサーバーから送られてくる


実際に検証してみる

次のようなコードをapp/page.tsxに書いてみましょう。

'use client';

export default function Page() {
  console.log(
    'Rendering Client Component'
  );

  return (
    <div>Hello from client</div>
  );
}

このとき、console.log()の出力がサーバー側にも出ることに驚いた方もいるかもしれません。

  • クライアント用JSバンドルとして動くだけでなく、最初の描画はサーバー上でも実行されるのです。

  • ただし、useEffect() などはサーバーでは動かず、クライアント側でのみ実行されます。


なぜそんな挙動になるのか?

これは、**React Server Components(RSC)**の影響によるものです。

App Routerは、できるだけサーバー側でUIを構築して軽いHTMLを返し、クライアントへのJS転送を最小限にする設計になっています。

そのため、Clientコンポーネントも含めて「まずはサーバーでHTMLを生成し、必要なJSだけあとから読み込む」というスタイルになります。

この挙動を正しく理解しておかないと、以下のような誤解をしがちです:

  • 'use client' ならすべてCSRされる → ✕

  • SSRしたいならServerコンポーネントでなければいけない → ✕(ClientでもSSRされる)


結局どう考えればいいのか?

  • Clientコンポーネントは「ブラウザでJSとして動く」という意味であって、レンダリング方法を決めるものではない。

  • App Routerでは、HTMLは基本的にサーバーで生成される(SSR/SSG)。

  • CSRとClient Componentは別モノとして理解するのが正しいです。

✅ 「クライアントコンポーネント = CSR」ではない。


おわりに

Next.jsのApp Routerは柔軟で強力な反面、挙動がややわかりにくい部分もあります。

今回は「クライアントコンポーネントなのにSSRされているように見える」という点に絞って解説しました。

今後は use client の制限や、Server Componentとの組み合わせ方など、さらに掘り下げていけたらと思います。

読んでいただきありがとうございました!

Next.jsのClientコンポーネントなのにSSRされてる?を理解する | 田邉豊のサイトへようこそ!