Hero img
NextjsはCSS Modulesを使うことにした

Nextjsがssrを強化しているため、その恩恵を受けるため、css-in-jsからmodules cssに切り替えた

Nextjsで使っていたEmotionからmodules cssに切り替えた


目次

  • Modules cssを使う理由
  • modules cssに置き換えて
  • 表示速度パフォーマンスの変化
  • コードの変化
  • 使ってみた感想
  • まとめ

Modules cssを使う理由

今まではEmotionとtailwind を使ったcss-in-jsが便利でずっと使用していましたが、パフォーマンスの問題、SSR非対応の問題、stateによる再レンダリング問題が発生してしまい、不便さを感じ始めました。
SSR非対応についてはEmotionが対応していくと公表していましが、Emotnionの特性上stateにかなり依存しているため、いつできるかが不透明。そのため、Moduels cssを使うことにしました。

modules cssに置き換えて

css-in-jsからmodules cssに切り替えてみた結果。

表示速度パフォーマンスの変化

modules cssに変えてみたらパフォーマンスがかなり改善された。 以下はLighthouseでの計測結果である。

modules-css-performance1 modules-css-performance2

Emotionの特性上jsでcssを読み込んでクラスを生成し、HTMLにクラスを付与する工程があるため、CLSが発生してしまう。これがLighthouseのスコアをかなり落としている。またファイルjs読み込み、jsのコード実行が入っているので、ページの表示速度も低下している。
ここまで改善されるのであれば、modulescssを使った方が良いと思える。

コードの変化

css-in-jsが良かった点はメディアクエリの書き方が楽だったためだ。2つの実際のコードは同じsylteである。

Emotionの場合
const hogecss = css`${tw`bg-white flex-initial w-11/12 md:w-sc6 lg:w-sc7  xl:w-sc5 max-w-7xl mt-1 md:mt-2 mx-auto  md:mx-0  md:px-1 lg:px-7 xl:px-10 pb-8`}
    filter: drop-shadow(0 0 4rem #f4fdff);
css-modulesの場合
.Mainarticles{
    background-color: white;
    flex: 0 1 auto;
    width: 91%;
    max-width: 80rem;
    margin-top: 0.25rem;
    margin-left: auto;
    margin-right: auto;
    padding-bottom: 2rem;
    filter: drop-shadow(0 0 4rem #f4fdff);
    @media screen and (min-width: 768px) {
        width:60vw;
        margin-top:0.5rem;
        margin-left: 0;
        margin-right: 0;
        padding-left: 0.25rem;
        padding-right: 0.25rem;
    }
    @media screen and (min-width: 1024px) {
        width:70vw;
        padding-left: 1.75rem;
        padding-right: 1.75rem;
    }
    @media screen and (min-width: 1280px) {
        width:50vw;
        padding-left: 2.5rem;
        padding-right: 2.5rem;
    }
}

css-modulesを使うとコード量が増えてしまい、メディアクエリも書かなければならない。
css-modulesでtailwindを使っていないからコード量が増えているのは間違いないが、書いてみると @applyが必要なのでコードがかなり読みづらくなってしまったので極力使わないことにしました。

もっと問題な点はmin-width:pxの部分であり、メディアクエリの数値を変更する時は全てのメディアクエリを変更しないといけなくなってしまった。これはメディアクエリを使う場合変数を使うことができないのでこのようになってしまった。
sassを使えば対応可能らしい。

ファイルの数

css-in-jsの場合は共通で使うものはコンポーネント化する。
そのページ独自sytleの場合はそのページのjsに記入する方法でcssを書いていたが、
css modulesの場合は共通部分はグローバルcssまたは、common.jsを作成して使用。
そのページ独自のcssの場合は新たにmodule.cssを作っているため、cssファイルの数が増えてしまった。
慣れの問題かもしれないが、管理がしづらい

使ってみた感想

css-in-jsに慣れてしまっている為か、再利用の観点で不便さを感じる。また、jsx側でimportを使用して、styles.hogecssと使用するため、少しコードが長くなってしまった。また、使い方が定まっていないのが悪いのだが、cssのファイルをどこで分けるのかがあいまいになってしまった。
それよりも問題なのはメディアクエリのwidthの数値を変数にできない点だ。
sassを使えばできるようだが、既存のcssでは対応できないらしい、別の方法として、containerを使えば変数対応は可能らしいが考えないといけないことが増えてしまうのであまり使いたくない。
css-modulesを使っていくと、これはglobal.cssに入れてしまって、あえてmodulesを使う必要があるのかを考えてしまった。
実は使う必要が無いのでは...?

まとめ

css-in-jsは書き方が楽、管理が楽だったため使っていたが、パフォーマンス問題、SSR問題が思ったよりも大きい弊害になっている。
css-modulesを使うとパフォーマンスも改善されたが、普通のcssを使うのと果たしてそんなに違いがあるのだろうか?実は一周回って普通のcssが一番汎用性高いのでは?

css-in-jsは記述が楽なのでパフォーマンスをそこまでこだわらない、スピード重視の場合は使う方が楽かもしれない。css-in-jsはこれからも使って行く。要するに適材適所かな?

関連記事

コメント

コメントを書く

質問や、間違いがありましたら、お気軽にどうぞ

※お名前とコメントの内容を入力してください。
※全てこのブログ上に公表されます。
※許可なく管理者によって修正・削除する場合がございます。 詳しくはプライバシーポリシーを参照ください