Facebookのテックスタック再構築の話
(engineering.fb.com)シンプルなPHPで始まったFacebookが、今回の新デザインに合わせてReact + Relay(GraphQL)へと移行してきた過程と教訓
CSS、JS、Data、Navigationそれぞれに、高速なアプリのための基本原則を適用
-
必要なリソースだけをできる限り速く送る
-
ユーザー体験のためのエンジニアリング体験
CSS
-
Atomic CSSによりCSSを80%削減し、不要なCSSはダウンロードしないように変更
-
アクセシビリティのためにremsを使用し、px → remsを手動変換する際のバグを減らすため、ビルドツールでこれを自動変換
-
Theming(ダークモード)のためにCSS変数を使用
-
ちらつき防止のためにInline SVGを使用(imgにSVGファイルを入れる代わりに)。これにより色の変更もランタイムで可能に
JS
- 3段階にCode-splittingしたJSを段階別に送信
Tier 1. 読み込み時にUI Skeletonを素早く表示するための基本レイアウト
Tier 2. 画面に見えているすべてのコンテンツを完全にレンダリングするためのJS。完全に動作可能で、Tier 2以降にコードが読み込まれても画面構成は変わってはならない
Tier 3. 画面表示後に必要なすべてのもの。ロギングコード、リアルタイム更新の購読など。
-
500KBのJSを50KBのTier 1、150KBのTier 2、300KBのTier 3に分割 → 読み込みと画面表示が非常に速く終わる効果
-
分割のおかげでA/Bテスト時にも、両側で必要なコードだけを受け取るよう設定可能に
-
Data-Driven Reactアプリの作成を支援するRelayの機能を利用し、どのデータを取得するかに応じて必要なコンポーネントだけを読み込むよう変更
-
ProductごとのJS Budget(予算)制度を導入。性能目標、技術的制約、製品上の考慮事項に基づいて予算を設定。時間が経ってもコードが増えるのを防止。
Data
-
Relayを利用し、すべてのデータフェッチをGraphQLを使うよう標準化
-
Relayのおかげで、ページリクエスト段階からまず必要なデータを並列でダウンロード。画面に素早く表示できるように
-
GraphQL内部拡張の@streamを使って、ニュースフィードのようなものを複数回のラウンドトリップなしに1回のクエリでデータを順次送信するようにした
-
@defer + React Suspenseで、今すぐ必要ではないデータは後で読み込むように
Navigation
-
SPAナビゲーション時に新しいページを読み込む際、リソース読み込み時間とラウンドトリップを減らすためにRoute Mapを構成
-
必要なときにできる限り速く、Route MapにRoute情報を分割して読み込み
-
リソースはできるだけ早く先にプリフェッチ(ホバー時にプリフェッチ、マウスダウン時にコードとデータを取得し、クリックが起きたらReactの状態を変更)
-
ナビゲーション間で空白画面を見せる代わりに、React Suspenseトランジションを活用して新しいRouteを取得する前に既存のRouteを継続して表示
-
EntryPoints(コード分岐ポイントとデータクエリをラップした小さなファイル)を使ってコードとデータのダウンロードを並列化
2件のコメント
Facebookの新デザインのCSSからわかったこと https://ja.news.hada.io/topic?id=1819
あわせて本文もご参照ください。
Relay - React向けの本番運用対応GraphQLクライアント https://relay.dev/