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との組み合わせ方など、さらに掘り下げていけたらと思います。
読んでいただきありがとうございました!