【S2お茶会】React Server Components(1/22)

s2お茶会
3月31日をもちまして、お茶会用の Instagram アカウントをクローズし、
公式アカウントに統合することになりました。
それに伴い、いつもお茶会レポート記事の最後に添えていた「今週のお茶菓子」のコーナーは終了となり、
今後は公式アカウントのストーリー機能を使ってのお茶菓子の投稿だけとなります。
公式アカウントでは、公開された実績についてやデザインチームによる実験的なグラフィックデザインなどを毎週更新しておりますので、これからはそちらをよろしくお願いいたします。

S2 Factory Official Instagram: @s2factory


今回は弊社の宮が「React Server Components」について話しました。

React Server Components


React とは、Facebook とコミュニティによって開発されているユーザインタフェース構築のための JavaScript ライブラリのことです。アプリケーション開発のベースとなるプログラム言語として広く使用されています。

そんな React から昨年末 「React Server Components」 というシステムが新しく発表されたのですが、今まで一種類しかなかったコンポーネントに、新しく二種類が追加されるそうです。

基本的な構成要素となるコンポーネントはこちらの三種類。

  • Server Components … 拡張子は .server.js
  • Client Components … 拡張子は .client.js
  • Shared Components … 拡張子は .js

従来のコンポーネントはこの中の Client Components に分類され、それのみでこれまでのアプリケーションは構築されていた。ということになるみたいです。
それぞれのコンポーネントは拡張子によって判断されます。

今はまだ RFC を募っている段階で、しかもデモ版しか触れないようような状況なので、今後どうなるかはわかりませんが、おそらく現在のアイデアが元になった技術が将来的に React に組み込まれるだろうといった話です。
ちなみに Next.js のチームと一緒に開発されているそうです。

それでは一つずつコンポーネントの特徴について見ていきましょう。

Server Components


これまでのコンポーネントは、クライアント側でダウンロードされクライアント側で動作していたのですが、このコンポーネントはダウンロードされることなくサーバー上で動作します。

さらに、Server Components 上のみで使用されている依存ライブラリのダウンロードも行われないため、全体的にダウンロードサイズが小さくなりクライアント側の待ち時間が短くなりました。この仕様を英語で zero impact on bundle-size というらしいです。

加えて、今まではサーバー上にあるリソースにアクセスしようと思うと、 API 越しでないとアクセスできなかったのが、このコンポーネントを使えば直接アクセスすることができるようになりました。
なので、試しにアプリを作ってみたけど API を用意するのは面倒、データベースを直で触りたいなーという時にはこれでまずやってみて、良さそうだと思ったら API を作るという使い方ができます。
ですが、公式によると、「現状、直接 Server Components からサーバーやデータベースにアクセスすることは推奨しない」ということらしいので、あくまでテスト用の使い方だということを忘れないようにしましょう。

また、サーバー側からクライアント側に新しい情報が渡った際には、変更部分だけがマージされるため、クライアント側の操作状態は保持されるようにもなっています。

いろいろな機能が使えて便利ですが、Server Components は従来の React で使えた state のようなクライアント専用の機能にはアクセスできません。クライアント専用の機能を使いたい時は Client Components か Shared Components 内に書いたものを import して使うようにしましょう。

Client Components


従来の React コンポーネントに相当し、これまで使われてきた state , effects などの全機能にアクセス可能、ボタンの onclick 機能のような interactivity を担当します。
ただし、ファイルシステムなどのサーバー専用の機能にはアクセスできません。

Server Components とは違って依存ライブラリと共にダウンロードされ、クライアント上で動作します。

「Client Components は Server Components を import できない」らしいのですが、Server Components にサーバー側のリソースへアクセスする機能を書かないとインポートできてしまうみたいです。今の時点ではそうなっている、というだけで将来的なことはわかりません。

Shared Components


サーバーとクライアント両方で動作します。

  • Server Components でインポートしていて、かつ、Client Components でしか書けないようなコードを書いていなければ Server Components として動く
  • Client Components でインポートした場合には、Client Component としてダウンロードされて動く

といった感じです。
サーバーとクライアント、そのどちらでも動く機能を作りたい時には Shared Components にコードを書いて共有するといった使い方になると思います。
ただし、state , effects のようなサーバー側で動かないようなコードを書いてしまうと Client Components として import されてしまうので注意が必要です。


以上が各コンポーネントの概要になります。
ここからは実際にそれぞれのコンポーネントがどのように使われているのかコードを読みながら少し見てみましょう。

server-components-demo


こちらを参考にコードを読んでみます。
これは、サイドバーから選択されたメニューに付随する情報をサーバーから取ってきてマークアップでレンダリングし、画面上で内容を編集すると、それがリアルタイムで右側の PREVIEW に同期され更新されるといった簡単なアプリケーションのソースコードです。




Server Components の使われ方

例えば、api.server.js という Server Components ですが、
ソースコードを見てもらうと、現状 Node.js が使われていて、如何にも node っぽいコードが書かれているのがわかると思います。

sendResponse という関数の中で、

  • アプリ内のどこの操作なのか
  • 編集状態かどうかの判別
  • 検索文字列

などの情報が入ったデータを json のような何かに変換してリクエストを送っています。
サーバーサイドレンダリングのように HTML が渡されるのではなく、必要な情報を json のような何かに変換し、 ReactApp という生成されたコンポーネントに渡しているようです。
クライアント側では受け取ったデータを tree の中にマージしながらレンダリングが行われ、操作状態などはそのままに変更箇所だけが更新されるといったイメージでしょうか。

Server Components からデータベースにアクセスする時はこのようにすればOKです。簡単に情報を取得できます。


Client Components の使われ方

Server Components では対応できないクライアント専用の機能を実装する時は、Client Components に書いて import しましょう。
デモでは、画像左側にあるサイドバー、選択されると開いたりなどの動作をするのですが、サイドバーの機能を SidebarNote.client.js に書き、それを Shared Components である SidebarNote.js から import して、さらに NoteList.server.js に import しています。
こうすることで、Client Componentsを使ってinteractiveな機能を実現しています。





Shared Components の使われ方

NotePreview.jsを例に見てみます。
画像右上の EDIT を押すと、先ほどの画像のように右側に PREVIEW 、左側に編集ボックスが現れるのですが、その状態の時はNotePreview.js を Client Components としてクライアント側にダウンロードさせ、それ以外の時は Server Components として振舞わせクライアント側にダウンロードさせないようにするという使い分けをしています。
必要な時だけダウンロードされるようにして、バンドルサイズを抑える使い方がされています。




デモのコードを読んでいると、関数名に unstable が使われているものなんかもあって、如何にも「まだ実験中だぞ」という主張が随所に見受けられます。

あまり操作がなく、クライアントの状態を保持しなければいけないということがないのならサーバーサイドレンダリングを使えばいいし、ユーザーとのinteractivity を意識しつつ、サーバーから返ってきたデータを部分的に書き換えると言った使い方をするのであれば Server Components を使うとか。

パフォーマンス面では SPA とサーバーサイドレンダリングのいいとこ取りなので、目的に応じて使いこなすことができれば非常に便利だとは思うのですが、コンポーネントの使い分けが面倒だという人には向いていないかもしれません。とはいえ、まだまだ開発途中なので、今後の発展に期待です。