Open3
React Server Components 雑まとめ
自分用スクラップとして作りました!
しっかりした情報は uhyo さんのスクラップへ:
このスクラップは、React Server Components についてまとめています。
公式ソースはこちら:
React Server Components 概要
- サーバーサイドで React コンポーネントをレンダーする新しい技術
- Facebook がいま研究していて、まだ開発段階
- React に、Client Components / Server Components という新しい概念を持ち込む
- Client Components は、従来通りクライアントでのみレンダーされるコンポーネント
- ステートを持ち、インタラクティビティを持つ
- Server Components は、サーバーサイドでのみレンダーされるコンポーネント
- サーバー上のリソースにアクセスするレイテンシを下げられる
- クライアントへは HTML を返すのではなく、独自のプロトコルを採用
- JSX を返したり
- Client Components の読み込み命令を返したり
- Concurrent Mode の Suspense を返したりする
- Shared Components というのもあり、場合によって Client / Server どちらでもレンダーできるコンポーネント
- データフェッチはしないけれど、外部ライブラリを読み込むから必要じゃないならクライアントに読み込ませたくない コンポーネントに使える
- Server Components から返されるとサーバーサイドで、Client Components から返されるとクライアントサイドで実行される
- デモでいうと、
NotePreview.js
コンポーネントは、Note.server.js
コンポーネントで呼ばれるときにサーバーサイドでレンダリングされ、NoteEditor.client.js
コンポーネントで呼ばれるときにクライアントサイドでレンダリングされる - 編集のプレビューをいちいちサーバーでやりたくないので、編集するとなったときに外部ライブラリも読み込めばいいよね
- Client Components は、従来通りクライアントでのみレンダーされるコンポーネント
- Concurrent Mode ともよくマッチする
- Server Components で Suspense を返すと、そこまでレンダリングしたら一旦クライアントに JSX を返却
- Suspense が解決したら、レンダー後の JSX を返す
- ここまで一つのコネクションでストリームする
- レスポンスの JSX には
J6
のようにそれぞれ番号がついていて、JSX の children に@6
のように埋め込んで分裂した JSX をリンクしている -
J6
が来てないのに@6
が来たら、そこで Suspense して fallback を表示していそう(推測)
動作の中身
デモのソースコードを見ながら動作を見ていく。
実装まで見ておらず、かなり推測入っているので注意!
- React クライアントは読み込まれると、
Root.client.js
でCache.client.js
のuseServerResponse
フックを呼び、/react
という API にリクエストしている -
/react
はlocation
というクエリを受け取る- LocationContext の値をそのまま渡している
-
Root.client.js
で初期化している- selectedId
- isEditing
- searchText
-
location
をApp.server.js
に渡し、サーバーでレンダリングする - こんなのを返す
-
途中で Client Components が現れたら、コンポーネントを読み込むよう
Mx
を返している- x には数値が入っていて、children に
@x
が入っていると、x に対応するMx
もしくはJx
が入る
- x には数値が入っていて、children に
-
レンダリングが終わったら、
Jx
として JSX を返している- J0 はルートの JSX
- 間に Client Components が挟まったり Suspense したりして分割されると、J1, J2, ...と分割されるっぽい
-
記事を選択すると LocationContext の値が変わってサーバーにリクエストが飛ぶ
- このとき、レスポンスは
useServerResponse
でキャッシュしているので、キャッシュヒットしたらリクエストせずにそれを返す
- このとき、レスポンスは
-
毎回全ての DOM を返しているが、クライアントでうまいことコンポーネントのステートを保持している
- key を返るとちゃんとコンポーネントが demount されるので、React の Shadow DOM の動作と同じっぽい(よく理解してない)