Frank Yan氏がReact ConfでFB5、すなわち、新しいfacebook.comで使用されているテクノロジやストラテジについて講演し、FacebookのCSS-in-JSへのアプローチなどについて論じた。
FacebookのWebサイトは、シンプルなPHP Webページとしてスタートした。その後、メッセージングやライブビデオなど、よりリッチでインタラクティブな機能がプラットフォームに加えられたのに伴って、スタックもCSSや生のJavaScript、Flux、React、Relayなどを組み合わせた複雑なものになり、ページサイズやパフォーマンスに負のインパクトを与えるようになった。プロダクトが必要とするユーザエクスペリエンスを構築するため、Facebookは、以下の要件に従ってゼロから再構築することを決定した — テーマをサポートする最新デザインのシステム、アクセシビリティの向上、ページロードの高速化、シームレスなインタラクション。新しいFacebookのWebサイトは、Rweact/GraphQL/Relayスタックを使用したシングルページアプリケーションになった。
Facebook特有の制限を考慮して、独自のCSS-in-JSライブラリを開発することにした。基本的なアイデアは、慣用的なCSSを破棄することなく、開発者が慣れ親しんだCSSの優れた部分を容易に維持管理できるようにする、ということだ。最も重視したのは可読性とメンテナンス性で、いずれも規模が大きくなった場合には問題となる。Yan氏はここで、FacebookのCSS-in-JSバージョンを実際に含んだコードサンプルを紹介した。
const styles = stylex.create({
blue: {color: 'blue'},
red: {color: 'red'}
});
function MyComponent(props) {
return (
<span className={styles('blue', 'red')}>
I'm blue
</span>
)
}
前述の例では、予期しないスタイルにつながる可能性のあるCSSの詳細度(specificity)に関わる問題が排除されて、最後に適用されたスタイル(red)が採用されている。
デザイナが最初に要求したのはダークモードだった。テーマ機能を実装するため、Facebookのチームは、カスタムCSSプロパティとも呼ばれるCSS変数を使用した。CSS変数はReact Contextが行うのと同じ方法で、値をエレメントのサブツリーに伝搬する。これにより、テーマ関連の値を保持するContextのユースケースは、ネイティブなブラウザ機能の使用によって代替される。SVGファイルをimg
タグに渡す代わりに、ReactコンポーネントとしてSVGアイコンを渡すことによって、テーマに従ってアイコンをカスタマイズすることが可能になり、余分なダウンロードをしなくても、実行時にアイコンの色を変えられるようになる。
アクセシビリティ関連では、フォントサイズが固定ピクセル(px
)を基本としたものから、フォントサイズ比例のrem
を基本としたものに変更された。
スタイルはJavaScriptファイルに組み込まれるので、静的チェック(スタイルオブジェクトの型チェックやlintなど)、実行時チェックのどちらも、JavaScriptツーリングを使って実施することができる。Facebookの開発環境では、実行時にエレメントがアクセス不能であったり、ダークモードに対応していなかったり、あるいはレンダリングが遅かったりした場合、開発者はそれを視覚的および機能的にブロックして、確認した問題を解決するために実行可能なレコメンデーションを提供することが可能になっている。
JavaScriptファイル内に置かれたスタイルルールから、各クラスがCSSプロパティ/バリューのペアを参照するような、アトミックCSSファイルが生成される。前述のコード例であれば、以下のようなCSS宣言が生成されることになる。
.c0 { color: blue}
.c1 { color: red}
これらのCSS宣言は、blueあるいはredのカラーを使用している場所ならば、どこでも再利用できる。再利用をショートネームと組み合わせることで、生成されるスタイルシートのサイズ削減が可能になる一方、CSSファイルのサイズと機能に見られる直線的な増加パターンは破られることになる。ダークモードを実装したにも関わらず、CSSファイルのサイズを413KBから73KBに削減することができた、とYan氏は述べている。
だが、最適化の余地はまだある。Yan氏は、コンポーネントコード内のstylex
スタイル宣言がなくなり、同じ値を持った定数CSSプロパティに置き換えられたことによって、サーバ側レンダリングとの互換性を維持しつつ、CSS-in-JSライブラリの使用に関わる実行時コストを大幅に削減できたことを示してみせた。
説明されたCSS-in-JSのアプローチは、単一目的のスタイリングユニット、ランタイムフリーなCSS-in-JSライブラリのLinaria、JavaScriptバンドルオプティマイザであるFacebookのPrepackに依存するという点で、Atomic CSSライブラリを連想させる。
Yan氏の講演の全内容は、他のコードスニペットや詳細な説明と合わせて、ReactConfのサイトで公開されている。ReactConfはFacebookの公式なReactイベントで、2019年はネバダ州ヘンダーソンで10月24、25日に開催された。