CSSのふりかえる - CSS-in-JSを捨てるタイミング？

# 1. はじまり

> 大学時代はサービスが企画した通り、正常に動作さえすれば、すぐにノートパソコンを投げ置いて、チームメンバーたちとチキンを食べに行った。

> **でも実際の仕事では違った、、**

> 効率的なコードを作成し、サービスの性能を高め、ユーザーのuxを高めることが非常に重要なポイントだった。
>
> 私ができる能力の中でどうすれば性能を向上させることができるかな？
>
> 高効率サーバー環境構築？ 無理、クールなバックエンドロジック作成？ 無理、フロントで余計なレンダリングを減らす？ふむ、、
>
> 悩みの中で好んで書いてきたCSS-in-JSが性能低下の恐れがあるという文を読んでもっと調べたくなった。


# 2. 開発者に優しい CSS-in-JS

> 個人的には
>
> 急にマージンを追加したくなる → 熟考の上、クラス名命名 → 他のスタイルと衝突するのでは？ 一度悩む → またHTMLファイルに戻る
>
> 上の過程がとても面倒だった。

> **そんな中、CSS-in-JSと知り合った。**

### CSS-in-JSとは? 

**名前の通り、CSSをJSファイルの中に作成するスタイリング方式だ。**

> 以下はCSS-in-JSライブラリの一つであるstyled-componentsの作成方法

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959845/08b536c7-b5b8-b552-1633-2f297c838ee0.png" width="100%"/>

https://styled-components.com/

> 強いてなぜCSSをJSファイルに？

# 3. CSS-in-JSの長所

### 1. 既存のCSSが持っていた様々な問題を解決してくれた

> Global Scope、Class名重複、CSSファイル間に重複、、など以前まで開発者を苦しめた色んな問題をもう気にしなく、スタイリングだけに集中できるようにしてくれた。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959845/691078c2-197f-79d0-c4d7-c386517ad8f0.png" width="100%"/>

>各問題点の詳細については、以下のリンクを参照

https://speakerdeck.com/vjeux/react-css-in-js

> CSSだけで解決するのが難しかった色んな問題をJSの手伝いを貰って解決ができた。

### 2. CSS-in-JSを使かうと

> クラス名を考えることに時間を使う必要がなくなり、
>
> 複数のCSSファイルを管理する必要がなくなり、メンテナンスが楽になる。
>
> また、最終的にどのようなスタイルが適用されるか悩まずにスタイリングだけに集中でき、
>
> JSのデータをCSSと共有し、JS環境を最大限活用できる。

---

> 上記のような長所が個人的にとても便利だったため、CSS-in-JSを好んで使ってきた。

> <font color="Crimson">**しかし、、こんなによさそうなCSS-in-JSにも大きな短所が存在した 😱😱**</font>

# 4. CSS-in-JSの短所

### 1. サービスが遅くなる
JSで作成したCSSコードを使用するためにはコンパイラで変換する作業が必要だ。


この時、必要な複数の装置がCSS-in-JSのライブラリを設置時に一緒に設置されるが

これらがJSバンドルを大きくさせる。 

大きくなったJSバンドルによってユーザーの初期進入は遅くなる。

また、CSS-in-JSはランタイム時にクラス名を生成した後、styleタグを生成するため、ユーザーの進入をさらに遅くした。

>*ランタイム：ライブラリがスタイルを解釈して適用する時間


### 2. インタラクティブなサイトでパフォーマンス低下のおそれが高い
JSの状態が変更され、コンポーネントがリレンダリングされるたびに

JS内部にあるCSSコードを一緒にパーシングしなければならないため、性能低下の恐れが高い。


>例えば
>
>アップルサイトのようにインタラクティブなサイトをCSS-in-JSに開発すると
>スクロールするたびにJSでCSSを再生成する。
>
>もちろんglobalStyleにインタラクティブなコードを定義しておけばある程度解決されるが
>管理ポイントが増えてコードが複雑になると結局globalStyleも複雑になってしまう。

下記の写真でCSS-in-JSライブラリの一つであるemotionを使用した時とSASS(CSS-in-CSS)を使用した時のレンダリング時間比較結果を確認することができる。
>CSS-in-JS使用時、平均約 **<font color="crimson">48%</font>** の性能低下が存在した！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959845/659fbaa9-75df-6896-dc6f-fc171e3ac097.png" width="100%"/>

https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-4g9b

 
>それでは今まで好んで使ってきたCSS-in-JSを捨てる時が来たのか？ 
>
> またCSS-in-CSSに戻る時かな？
>
>上記の質問に答える前に、複数のCSSスタイリング方法についてもう一度調べてみたくなった。


# 5. スタイリング方式の比較

> 様々なスタイリング方法を比較してみよう

### 1. CSS-in-JS
**JSファイルの中でCSSを作成する方式**

>複数のCSSファイルを管理する必要もなく、コンポーネント単位でスタイリングするため、メンテナンスも楽だ。
>
>またJSの変数、関数などを利用できるという点も大きなメリット。
>コンポーネントレンダリングに必要なCSSだけを取得するので効率的。
>
>⚠️BUT
>
>ライブラリ設置によるJSバンドルのサイズ増加して初期進行が遅くなる
>JSの状態が変わるごとにCSSも一緒に新しくパーシングされてインタラクティブなサイトでは性能が悪い。

### 2. CSS-in-CSS
**分離されたCSSファイルからCSSを作成する方式**

>JSと分離してCSSを作成するため、性能低下の恐れが低い。
>レンダリング時にすべてのCSSを取得のでインタラクティブなサイトで良い性能を見せる。
>
>⚠️BUT
>
>管理すべきファイルが増加し、気を使わなければならない部分も増える傾向がある。
>すべてのCSSを取得して来るのが非効率的場合がある。


#### CSS Preprocessor & CSS_modules
**既存のCSSの問題点をある程度解決したスタイリング方式**

**1. CSS Preprocessor**
> CSSにプログラミング的要素を追加して効率的なCSSコードを作成できる。
>
>⚠️BUT 
>
>クラス名の問題を解決できない(BEM方法論またはCSS Modulesを一緒に使ったら解決できる)。
>コードが複雑になると、むしろメンテナンスに時間がかかる可能性が高い。

**2. CSS Modules**
> CSSをモジュール化して使用するので、クラス名重複を完全に防止してくれる。
>
>⚠️BUT 
>
>CSS をファイルごとに分けて作成するため、管理するCSSファイルが多くなる可能性がある。

#### Utilty first css(tailwindCSS)
**予め定義して置いたCSSを呼び、クラスを通じて適用させるスタイリング方式**

> クラス名を悩む必要がなくファイル間移動なしで作業できる。
> ビルド時に最終CSSバンドルのサイズを自動的に最小化する。
>
>⚠️BUT
>
>クラス名が汚くなる。
>定義して置いたクラス名に適応するまでには検索しながら作業をしなければならない。 
>また、協業時にデザインが出るまでCSSを完璧に定義しておくのが難しい。


### 3. その他よさそうなスタイリング方式

#### Zero-runtime CSS in JS ( Vanilla-extract、Linaria、、)
**ランタイムがとても短いCSS in JS**

>開発者フレンドリーな環境だし、性能低下はほとんどない。
>
>⚠️BUT 
>
>ランタイムが名前のように完全に0ではない。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959845/73cdfb8c-d479-bc0a-ce43-042c7f60e59e.png" width="100%"/>

https://vanilla-extract.style/


#### On-demand Atomic CSS
**デザインが決まっていないと使いにくかった従来のUtility first css方式を改善したスタイリング方式**

> HTML作成時にCSSを自動的に定義

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959845/b96b76b9-92fc-3653-7f81-8dafe64a77af.png" width="100%"/>

https://github.com/unocss/unocss


# 6. 結論は?

>色んなスタイリング方法を比較してみた結果。
>
>各方法ごとに長所と短所がはっきりしてあるので、この方法が最高だ！ という結論を出すのは現時点では難しいと感じた。
>
> プロジェクトの進行時にどのような部分に重点を置いているのかをちゃんと判断してスタイリング方式を採用することが重要だと思った。


# 7.要約

#### コンポーネントベースの開発

<font color="ForestGreen ">**👍 CSS-in-JS** : 活性化されたコンポーネントに関連するスタイルのみを取得するため、効率的。</font>

<font color="Crimson">**🚫 CSS-in-CSS** : 見えないコンポーネントに関連するスタイルを含め、すべてのCSSを取得するため非効率的である。
</font>

#### インタラクティブなウェブページの開発
<font color="ForestGreen ">**👍 CSS-in-CSS** : レンダリング時にすべてのCSSをロードするので、コンポーネントが変更されてもCSSに影響なくすぐに適用される。</font>

<font color="Crimson">**🚫 CSS-in-JS** : 状態が変更され、コンポーネントがリレンダリングされるたびにJS内にあるCSSコードを一緒にパーシングしなければならないため、性能低下の恐れがある。</font>

#### コンテンツの多いウェブページの開発
<font color="ForestGreen ">👍 効率的速度が早い**CSS-in-CSS**</font>

#### 開発を早くしなければならない状況
<font color="ForestGreen ">👍 開発者に優しい**CSS-in-JS**。</font>

#### 性能を優先しなければならない状況
<font color="ForestGreen ">👍 性能面で安定性のある**CSS-in-CSS**。</font>

# 8. さいごに

どうしても性能を優先するよりは開発者にやさしい環境でReactやNextでコンポーネント基盤の開発をしているため、何も考えずに常にCSS-in-JSを選択してきた。

これからはプロジェクト状況に合わせてスタイリング方式を選択し、ユーザー満足度がより高いサービスを提供したい。

#### ※ 参考
https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-4g9b

https://speakerdeck.com/vjeux/react-css-in-js

https://www.samsungsds.com/kr/insights/web_component.html