CSS in JS 2022-10
2022年10月時点でのCSS in JSについてのメモ。Zero Runtime CSS in JSやZero-runtime CSS in JSライブラリの比較など。
Table of Contents
ReactではCSSを記述する上で、現状styled-componentsやemotionをはじめとしたRuntime CSS in JSライブラリが支配的ですが、パフォーマンスなどを考えると本来静的なCSSファイルつまりZero Runtimeの方が好ましいです。今までさほど問題に上げられて来ませんでしたが、React 18によって今後Zero Runtime CSS in JSを使う圧が強くなっていく可能性が高いです。
Runtime vs Static
Ref: https://github.com/reactwg/react-18/discussions/110
- Runtime CSS in JSは現状”レンダリング中”にstyleを挿入するケースで並列レンダリングが非常に遅くなる
- コンポーネントが順次レンダリングされていくと、その度に新たなスタイルが挿入され再計算が発生する
- 競合するルールが存在した場合、ルールが先行して追加されるため再計算が複数回発生する
- このユースケース用にuseInsertionEffectが追加された
- DOMの参照にアクセスできないことを除いてuseLayoutEffectとほぼ同様に振る舞う
- このユースケース用にuseInsertionEffectが追加された
- React自体にこれらの問題を解決する計画はない。
- 静的に抽出されたスタイルに使用し、動的な値に単純なインラインスタイルを使用することを推奨する
- 効率的な解析や、キャッシュが強力であるという点でも優れている
- ページ数に比例してCSSファイルサイズが肥大化するという懸念が以前はあった
- Atomic cssやTailwind cssのようなユーティリティスタイルなどを有効活用することで、ファイルサイズは横ばいになる
- 静的に抽出されたスタイルに使用し、動的な値に単純なインラインスタイルを使用することを推奨する
Zero-runtime CSS in JSの比較
- Linaria
- https://linaria.dev/
- emotionやstyled-componentsライクなAPIなため移行が容易
- @linaria/atomic: atomic styles用
- vanilla-extract
- https://vanilla-extract.style/
- 型が強力
- 仕組みが他ライブラリと大きく異なり、移行には慣れが必要
- CSSなどのファイルをJSで読めるようにする提案が存在し、将来的にこうなるのではないか?という設計になっている
- CSS ModulesライクなAPI
- @vanilla-extract/sprinkles: ユーティリティクラスの提供
- @vanilla-extract/recipes: variantを持つスタイルの生成
- Twin
- https://github.com/ben-rogerson/twin.macro
- Tailwind CSSが好きな人はこれ一択でいいのでは?
CSSファイルサイズが肥大化する問題への対処
ほとんどのライブラリで対応手段が用意されている上、現在においてはほとんどの場合無視できる程度の負荷しかない。それよりもコストの高いCSSの記述などを気にした方がいい。
- Linaria
- @linaria/atomic
- vanilla-extract
- @vanilla-extract/sprinkles
- Twin
- 当然Tailwind CSSを積極的に利用していくこと
- 他
- Utility CSSクラスを何らか手段で用意しておけば良い