はじめに
12月21日、Facebookから予期せぬクリスマスプレゼントが配られました🎁
reactjsによって、こちらにReact Server Componentsなるものが突如発表され、React界隈でとても話題になっています。
僕もTwitterでこのニュースを見つけて、ReactでServer???なんかやばそう。そう思いながらこのページを覗くと、説明はどうやら動画のみっぽい。
しゃーねーなーっつって、動画開いたら再生時間57分。当然全部英語...。おいおい、頼むよほんと。
まあ眠くなりかけながらなんとか見終えて、個人的にまとめてみました。
僕がこれ書いてる時点では、ある程度体系的な日本語での記事はほんとにいくつか散見される程度だったので、
日本最速(ほぼ)で紹介します?
それじゃー早速どうぞ。
対象の読者
- Reactへの知見がある程度ある方
- React Server Components興味あるけど、動画長げーしって方
React Server Componentsの概要
React Server Componentsは、サーバーサイドにComponentsを置いて、そこからデータ取得を行うことで、余分なネットワーク通信を介したデータのやりとりを減らし、アプリケーションの高速化を実現します。
Componentの種類には
- ${Component名}.client.js (フロントでレンダリング)
- ${Component名}.server.js (サーバーサイドでのレンダリング)
- ${Component名}.js (Shared Component、詳細は後述)
の3つがあります。
何がいいか
1.backend内で直接データをfetchできるため、取得速度が早い
export default function NoteList() {
const notes = fetch('http://localhost:4000/notes').json(); // ラップしなくて良い
return notes.length > 0 ? (
<ul>
{
notes.map(note => (
<li>
<SidebarNote note={note} />
</li>
))
}
</ul>
)
}
動画では上記のようなコードが紹介されています。server.jsファイルでも、普段のReactの記法とに大した差分はありません。
言うとすれば、notesのfetch処理は同期的に扱われるため、普段のようにuseEffect等のhooksでラップする必要はありません。
こちらは.server.jsファイルなので、サーバーサイドでのレンダリングがされます。
このようにデータの取得をserverレンダリングのコンポーネントで行うことで、スムーズなデータの受け渡しが可能となり、レンダリングが高速になります。
2. server.jsのcomponentで使われるライブラリはnode_modulesに入らないため、clientでの余分なダウンロードがいらない
動画では日付をフォーマットするために、date-fnsというライブラリを用いて説明がされていました。これを用いた日付のフォーマット処理をserver.jsで行うことにより、date-fnsがフロントにビルドされるnode_modulesのディレクトリに居なくなります。
これによって少しでもビルドするモジュールの容量を減らすことができ、アプリケーションの高速化に繋がります。
3. SSRと異なり、client-sideのStateが保持される
ここまで聞いて、いやいやSSRやんけ。って思いましたね?
動画内では、SSRとの違いとしてStateの扱いについての違いが挙げられていました。
React Server Componentsでは、useState等で管理されるクライアントのstateが初期化されず、クライアント側でそのまま保持されます。
これはReact Server Componentsがページ全体のHTMLへのレンダリングをせず、必要なComponentのみ再レンダーが走るよう、特殊なフォーマット形式(一見jsonに似てるけどそれともちょっと違う)への変換を行うために可能なそう。
4. SharedComponentを使って、server / clientでのレンダリングが柔軟に切り替えられる
サーバーサイドでレンダリングを行うserver.jsファイルに書かれたComponentはフロントとのインタラクティブ性を持つような実装はできません。
つまり、eventListener(onClickとかね)やuseStateは使えません。
そのため、これらのフロントとのインタラクティブ性が必要なComponentはclientでのレンダリングを行い、そうでない部分に関してはサーバーサイドでのレンダリングをするのが理想的といえます。
Shared Component(${Component名}.jsファイルに定義される)はどんなComponentをimportしているかによって、クライアントによるレンダリングを行うか、サーバーサイドでのレンダリングにするかが決定されます。
動画ではnoteのプレビュー機能を例に解説されていました。
noteは完成された投稿を閲覧するだけの場合であれば、フロントとのインタラクティブ性は特にないため、サーバーサードによるレンダリングで十分そうです。ですが、プレビュー機能となると、ユーザーの修正に合わせて常に表示内容が変更される必要があります。この場合はフロントでのレンダリングが必須です。
Componentの切り分けを適切に行うことで、Componentを共通化しながら柔軟にどちらでレンダリングするかをハンドリングできます。
終わりに
いかがだったでしょうか?基本的にはデータのfetchをサーバーサイドでレンダリングするComponentで行い、フロントとのインタラクティブ性があるComponentで使う場合はpropsとして渡すと言う感じになりそうです。
詳細については、下記の動画を参考にしてください、また、demoのrepositoryも公開されているので、自分も後で触ってみようかと思います。
正式に公開されるのが楽しみですね。
参考