How React server components work: an in-depth guideを読んでServer Componentsについて理解する
目的
How React server components work: an in-depth guideを読んで要点整理する。
RSCって何?
React server components (RSC)はエキサイティングな新機能で、近い将来、ページロードのパフォーマンスやバンドルサイズ、そしてReactアプリケーションの書き方に大きな影響を与えるらしい。
サーバーとクライアント(ブラウザ)が協力してReactアプリケーションをレンダリングすることを可能にした。つまり一部のコンポーネントをサーバーがレンダリングし、一部のコンポーネントをブラウザがレンダリングすることを可能にした。
Server Side Rendering(SSR)と一緒?
違う。SSRはReactツリーを生のhtmlにレンダリングする環境をシミュレートするもので、サーバーとクライアントのコンポーネントを区別せず、同じようにレンダリングする。一旦SSRは置いておくのが吉。
RSCはここがすごい
RSC以前は、Reactコンポーネントはすべて「クライアント」コンポーネントで、すべてブラウザで実行された。では、なぜサーバー上で何かをレンダリングしたいのだろうか?それは、サーバー上でのレンダリングには、ブラウザよりも優れている点があるからだ。
- サーバーはデータソースとより密接に連携しているため、ブラウザよりも迅速にデータを取得することができる
- 重いコードモジュールを楽に利用することができる
つまり、RSCは、サーバーとブラウザーがそれぞれ得意とすることを可能にする。サーバーコンポーネントはデータのフェッチとコンテンツのレンダリングに集中でき、クライアントコンポーネントはステートフルなインタラクティブ性に集中できるため、ページロードが速くなり、javascriptバンドルサイズが小さくなり、ユーザーエクスペリエンスが向上する。
別の言い方をすれば、RSCは役割分担を可能にするためのもの。サーバーができることを前もってやっておき、残りはブラウザに任せる。
サーバーコンポーネント・クライアントコンポーネントの分割
拡張子によって使用できるコンポーネントが変わる。.server.jsxだとサーバーコンポーネント、.client.jsxだとクライアントコンポーネント、どちらでもなければ両方のコンポーネントを使用できる。
また、大事なことは、クライアント・コンポーネントはサーバー・コンポーネントをインポートできない。以下の例はだめ。
// ClientComponent.client.jsx // NOT OK: import ServerComponent from './ServerComponent.server' export default function ClientComponent() { return ( <div> <ServerComponent /> </div> ) }
ただし、ReactNodesのpropsとして取り込むことはできる!
// ClientComponent.client.jsx export default function ClientComponent({ children }) { return ( <div> <h1>Hello from client land</h1> {children} </div> ) } // ServerComponent.server.jsx export default function ServerComponent() { return <span>Hello from server land</span> } // OuterServerComponent.server.jsx // OuterServerComponent can instantiate both client and server // components, and we are passing in a <ServerComponent/> as // the children prop to the ClientComponent. import ClientComponent from './ClientComponent.client' import ServerComponent from './ServerComponent.server' export default function OuterServerComponent() { return ( <ClientComponent> <ServerComponent /> </ClientComponent> ) }
RSCの詳細
1. サーバーがレンダリング要求を受け取る
"ルート "コンポーネントは常にサーバー・コンポーネントであり、他のサーバーまたはクライアント・コンポーネントをレンダリングする可能性がある。
2. サーバーはルート・コンポーネント要素をJSONにシリアライズする。
サーバーはルート・サーバー・コンポーネントを、ベースとなるhtmlタグとクライアント・コンポーネントのツリーにレンダリングする。そしてこのツリーをブラウザに送信し、最終的にブラウザでレンダリングを行うことができる。
クライアント・コンポーネントやベースとなるhtmlタグに渡すすべてのpropもシリアライズ可能でなければならない。つまり、サーバコンポーネントから、イベントハンドラをpropとして渡すことはできない!
// NOT OK: server components cannot pass functions as a prop // to its descendents, because functions are not serializable. function SomeServerComponent() { return <button onClick={() => alert('OHHAI')}>Click me!</button> }
3. ブラウザがReactツリーを再構築する
ブラウザはサーバーからJSON出力を受信し、ブラウザでレンダリングされるようにReactツリーの再構築を開始する。
残タスク
シリアライズやモジュール参照など、RSCをより正確に理解するヒントがあった為、改めて深堀りしたい。
今後ドキュメントを参照したり、ハンズオンをしたりしながら身につけていく予定。