最近のNext.js(React)でのCSS戦略
はじめに
Reactの実装においてスタイルを当てる手段は複数ありますが、今回は昨今のNext.js(特にApp router)環境下でのCSS戦略について個人的な見解を記していきたいと思います。
選択肢が多すぎるスタイリング
そもそもReactで実装する上でアプローチできるスタイリングの段が多すぎる(と感じる)現状。
簡単にですが、現状のフロントエンドにおいてスタイリング方式は下記のような属性ごとに分けられます。
- CSS Preprocessor & CSS modules
- CSS-in-JS
- Utilty first css(tailwindCSS など)
ちなみにState of CSS 2022によると、直近ではCSS ModulesやTailwind CSSが一番多く使われているデータが上がっています。
Next.js(v13~)の流れを受けて
Next.js v13以降では、新たにApp Routerが導入され、React Server Components(RSC)の使用が推奨されています。
この変化により、CSS戦略も影響を受けています。
特にスタイリングにおいてCSS in JS 周りの使用に制限がかかったことが顕著に挙げられます。
実際公式ドキュメントにはその内容が明記されています。
Warning: CSS-in-JS libraries which require runtime JavaScript are not currently supported in Server Components.
Good to know: We're testing out different CSS-in-JS libraries and we'll be adding more examples for libraries that support React 18 features and/or the app directory.
このことから RSCを用いる場面では、軒並みCSS in JS の使用は検討した方がいいのではないかと感じています。
Next公式に明記はないものの、「kuma-ui」のようなRSCをサポートしているライブラリも存在します。
少なくとも取るべきCSSの手段として、RSCのサポートがされているものであるかどうかは今後の判断材料に加えるべきであると考えます。
個人的には上のvanilla-extract のような静的なCSSファイルを吐き出すものについては、
概ねRSCでも使えそうなイメージなのですが、如何せん公式よりはっきりと明記されていないのでモヤモヤします。、
結局どうするべきか
上記を考慮した上で、昨今のNext.jsの環境下においては CSS Modules
の採用が適していると感じています。
CSS Modules の採用理由
その理由が下記になります。
- 公式によるサポート:Next.jsドキュメントでもCSS Modulesの使用が推奨されている。
- React Server Componentsとの互換性: 最新のNext.jsではReact Server Components(RSC)の使用が推奨され、CSS ModulesはRSCとも問題なく動作する。
- 可読性と保守性:素のCSSで書けるので、学習コストがかからない。他の開発者が参加しやすい。
公式がきちんと推奨されている点で一番安心できます。あとやっぱりスタイルは普通にCSSで書きたいなとも思いますし、
一方で、Typescriptの標準サポートが不足している点はデメリットです。
しかし、この問題は特定のツールを使用することで概ね解消できます。
上記に加えて、CSS Modulesだけでは不足する場合は、Tailwind CSSを併用することも手段としてアリです。
ただ、これは今回のケースでの見解です。
下記のようなケースでは、CSS in JSの使用も考慮するべきであると考えます。
- 非Next.jsプロジェクト
- 動的なスタイリングが多い場面
- アプリライクなプロジェクト
逆にLPやサイト制作に近いような比較的動的スタイルが少ないケースでは、わざわざCSS in JS を使用するメリットは薄いと思われます。
最後に
少し余談ですが、Emotionのようなランタイムで動作するものはパフォーマンスの観点で優れておらず、React公式でもその問題点が提言されています。
最近ではCSS in JS界隈では全体的にlinariaやvanilla-extractのようなゼロランタイムに向けた流れ?があるように感じます。
間違っていること等あれば、ご指摘いただけますと幸いです。
この辺の意思決定に関して、ご意見あればぜひ伺いです。、!
Discussion