654 文字
3 分
CSS in JS 2022-10
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 クラスを何らか手段で用意しておけば良い