O hirunewani blog

CSS in JS 2022-10

Created at

2022年10月時点でのCSS in JSについてのメモ。Zero Runtime CSS in JSやZero-runtime CSS in JSライブラリの比較など。

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とほぼ同様に振る舞う
  • 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

CSSファイルサイズが肥大化する問題への対処

ほとんどのライブラリで対応手段が用意されている上、現在においてはほとんどの場合無視できる程度の負荷しかない。それよりもコストの高いCSSの記述などを気にした方がいい。

  • Linaria
    • @linaria/atomic
  • vanilla-extract
    • @vanilla-extract/sprinkles
  • Twin
    • 当然Tailwind CSSを積極的に利用していくこと
    • Utility CSSクラスを何らか手段で用意しておけば良い