はじめに
皆さんはNext.jsを使ってWeb開発をしていますか?私はNext.jsが好きでよく利用していますが、少しだけ不満に思う点があります。それはClient Componentsに関することです。
Next.jsのApp Routerでは作成したコンポーネントはデフォルトでサーバーのみでレンダリングをされるServer Componentsとなります。また、Server Components登場以前からあるいわゆる「標準的な」Reactコンポーネント(Client Componentsと呼ばれる)に切り替えて使うこともできます。
しかし、Client Componentsという名前だとまるでクライアントのみでしかレンダリングされない見たいじゃないですか。Server Componentsがサーバーでのみレンダリングされることから余計にそう思ってしまいます。
実際、私自身もNext.jsのApp Routerを学び始めの頃はずっとそう思っていました。元々Pages RouterからNext.jsを使い始め、App Routerに移行した際、しばらくの間、ドキュメントを読まずに「雰囲気」で使っていた(今もかもしれません…)のですが、ある日ドキュメントを読んで初めて気づきました。
個人的にはPages Routerからしっかり学んでいた方はClient Componentsの誤解はないかもしれないですが、App Routerからやり始めた方や過去の自分みたいに全くドキュメントを見ない人は誤解してしまっているかもしれません。
ってことでドキュメント見ながら、Next.jsのレンダリングについてご紹介します。
私自身、まだWeb開発初心者なので、内容に誤りがあるかもしれません。その場合はぜひご指摘いただけると嬉しいです。
Client Components
Next.jsのレンダリング > クラアントコンポーネントを見ると、すぐにサーバー上でレンダリングされるということが書いてありました。
でも、事前レンダリングってなんだってなりますし、サーバー側でレンダリングして、どうやってインタラクティブなUIを実現するのでしょうか。もう少し読み進めてみます。
下のスクショではどのようにClient Componentsがレンダリングされているかが書かれています。簡単に説明すると、サーバーで静的HTMLをレンダリングし、それがブラウザに表示された後、JSファイルをダウンロードしてインタラクティブなUIを実現している、という流れです。
スクショの最後にある「水分補給」とは、サーバーでレンダリングされたHTMLにクライアント側でインタラクティブ性を加えるプロセスのことを指します。この点については、akiさんの記事が視覚的に非常にわかりやすいです。
これによって、クライアント側でJSのロード、実行に時間がかかり、Reactコンポーネントがレンダリングされず、しばらく画面が白くなってしまう問題や、レンダリング前の要素のないHTMLがクローラーに渡されることでSEOの低迷してしまう問題を解消しています。
Server Components
Server Componentsについて詳しく説明すると本題から逸れてしまうので、ここでは簡単に触れるだけにします。当然ながら、Server Componentsはサーバー側でレンダリングされます。
また、JSをロード・実行し、インタラクティブにするプロセスであるハイドレーションは行われていません。詳しいレンダリングの詳細に「水分補給」という言葉がありますが、これはクライアントコンポーネントの話をしています。
結論
Client Componentsは、サーバー側で初期HTMLを生成し、クライアント側でハイドレーションを通じてインタラクティブ性を持つため、サーバーとクライアントの両方でレンダリングされます。一方、Server Componentsはサーバー側でのみレンダリングされ、生成された静的HTMLがクライアントに送信されます。
| Server Rendering | Client Rendering | |
|---|---|---|
| Client Components | ⭕️ | ⭕️ |
| Server Components | ⭕️ | ❌ |
警告
たとえClient Componentsでフックを使用せず、インタラクティブ性がゼロであっても、そのコンポーネントはクライアント側でのハイドレーションが行われます。
余談
じゃあ、なんて名前にするのがいいかという話なんですが、Standard Componentsというのはどうでしょうか。これは「標準的な」Reactコンポーネントを表すのに適切な気がしています。これに伴って、ディレクティブも"use standard"とかにしては良いのではないでしょうか。
"use standard";
import { useState } from "react";
export const Home = () => {
const [count, setCount] = useState(0);
return (
<div>
<h1>Counter Example</h1>
<p>Current Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
これはマジで余談なんで呼び飛ばしてもらって構いません。もしなにか良さげな名前あったらコメント欄とかで教えてほしいです!



