CSS Modulesを型安全に扱える「CSS Modules Kit」をAstroプロジェクトに導入する
#69
2025-07-30

CSS Modulesを型安全に扱える「CSS Modules Kit」をAstroプロジェクトに導入する

CSS Modulesを型安全に扱える「CSS Modules Kit」をAstroプロジェクトに導入する
2025-07-30

CSS Modulesを型安全に扱える「CSS Modules Kit」をAstroプロジェクトに導入する

#69

モダンフロントエンドにおけるスタイリングメソッドは数多くありますが、その中でも自分はCSS Modulesをよく使います。

  • HTMLとCSSをそれぞれ別ファイルに書くので関心の分離が進む
  • CSSクラスのローカルスコープ化ができる (当たり前)
  • 生のCSS構文が使える (当たり前)
    • Tailwindをだいぶ昔にちょっと使ったきりなので知識が浅くて恐縮なのですが、例えばTailwindで複雑なセレクタを表現するにはArbitrary Valuesと呼ばれるものを使用する必要があり、ちょっとサンプルを覗いてみた感じソースコードの可読性が下がりそう(?) @applyを使ってCSSファイルに切り出す手法もあるみたいですが、本末転倒感🤔
  • generateScopedNameオプションを指定することによってどのようなクラス名を要素に当てているのか本番環境では隠蔽する(=ハッシュ値のみにする)ことができる
    • だって要素に対してどういう命名してるのかエンドユーザーにバレるの、恥ずかしいでしょ?
  • CSS Modules独自の拡張構文が使える (参考)
    • 紹介した手前申し訳ないですが自分は使ったことないです🙇

あたりが主な理由なのですが、それとは別に今まで「どうにかならないかな〜」と薄々感じていたのが 型安全じゃない! ということでした。

例えばCSSファイルに.informationというクラスが存在しないのにHTMLでstyles.informationを参照していてもエラーになりませんし、逆にHTMLでstyles.informationを参照していないのにCSSファイルに.informationのスタイルが置かれていてもエラーになりません。 (後者は基本的にはTypeScriptのエコシステムに絡んでいない部分のはずなのでワガママではある)

あとはコードジャンプができないということです!

本当はクラス名をクリックしたらCSSファイルの該当箇所まで飛んでいきたいのです🕊️

これらを解決してくれるソリューション無いかな〜とやっとの思いで重い腰を上げてみたところCSS Modules Kitという素晴らしいツールがあったので、Astroプロジェクトに導入した時の作業手順を備忘録として残しておくことにします。

前提

今回は現在ご覧になっている当ブログのリポジトリにCSS Modules Kitと関連Stylelintプラグインを導入します。

フレームワークはAstroで、中に少量のAstroコンポーネントと多量のReactコンポーネントが混在している形になります。

(2025年7月にリリースしましたが、デザイン・コンテンツ移行込みで開発に1年半程度かかりました😭)

また、開発環境のエディターはVSCodeとします。

Tipsエディターについて

詳しくは公式ドキュメントをご確認いただきたいのですが、CSS Modules Kitは使用しているエディターによって導入方法が異なり、例えばVSCodeは拡張機能をインストールすれば良いだけなのに対してZedは拡張機能をインストールしたうえで設定ファイルを書き換える必要があったりします。シェア率的にVSCodeもしくはVSCodeフォーク(CursorやVSCodiumなど)のエディターを使用している方が大半でしょうから、今回はVSCode以外のエディターを使用しているケースは無いものとして考えます。

詳しくは公式ドキュメントをご確認いただきたいのですが、CSS Modules Kitは使用しているエディターによって導入方法が異なり、例えばVSCodeは拡張機能をインストールすれば良いだけなのに対してZedは拡張機能をインストールしたうえで設定ファイルを書き換える必要があったりします。シェア率的にVSCodeもしくはVSCodeフォーク(CursorやVSCodiumなど)のエディターを使用している方が大半でしょうから、今回はVSCode以外のエディターを使用しているケースは無いものとして考えます。

拡張機能をVSCodeにインストールする

mizdraさん名義になっているCSS Modules Kitという拡張機能をVSCodeにインストールします。

Marketplaceはこちら

codegenをインストールする

インストール完了後、npm-scripts(package.json)にcodegen実行用コマンドを登録しておきます。

tsconfig.jsonを編集する

あくまで上記はこのブログのリポジトリの場合の設定値ですが、この中で重要なのは

  • include
  • compilerOptions.rootDirs
  • compilerOptions.paths

の3つかなと思います。

include

公式ドキュメントには

という記載があるのですが、自分の環境ではincludeを明示的に指定しないとcmkを実行しても何も出力されませんでした🤔

compilerOptions.rootDirs

cmkを実行すると(デフォルトでは)generatedディレクトリ配下にsrcディレクトリ配下の構造がまるっとコピーされ、それぞれのディレクトリにCSS Modulesの型定義ファイルが自動生成されます。

で、今生成したgenerated/src/**/*.module.css.d.tsからモジュールの型定義を引っ張ってきてsrc/**にて使用する、という設定をここで指定しています。

compilerOptions.paths

インポートエイリアスを設定している場合は指定必須です。

公式ドキュメントでは特に言及されていませんが、ここでもgenerated配下を指定に含めてあげないと、VSCodeではエラーが出るのにCI(astro check)ではエラーにならないということが起きたので忘れず指定するようにします。

codegenを実行する

おそらくここまで手順通りに実行するとCSS Modulesが型安全に扱えるようになっているかと思います! (コードジャンプもできるようになっているはずなので試してみてね)

使用されていないCSSのクラスにもエラーが出るようにする

「存在しないクラス名を指定してしまっているHTMLに対してエラーを出す」ということは実現できましたが、その逆、「使用されていないCSSのクラスに対してエラーを出す」ということがまだ実現できていないので設定していきます。

といっても設定は先述のものに比べたらめちゃくちゃ簡単で、Stylelintのプラグイン(@css-modules-kit/stylelint-plugin)をインストールし、

Stylelintの設定ファイルでextendするだけです!

するとなんということでしょう、未使用のCSSクラスに対してエラーが出るようになったではありませんか。

CSS Modules Kitに関する雑記

generatedディレクトリ配下のバージョン管理

個人的にgeneratedディレクトリ配下はバージョン管理不要だと思っているので.gitignoreに追加しています。また、直接編集することもないのでESLintやPrettierのignoreリストにも入れています。

が、こうすると例えばチーム開発においては新規参画者のcodegen未実行環境で型がハマらずにエラーになってしまうといった問題が発生することが考えられます。

npm installnpm run genを実行すれば解決可能な話ではありますが、コマンドを2つ実行するのすら億劫な方もいらっしゃるでしょう。

そういう場合は最近地味に来てる(?)Makefileでまとめちゃうのもアリなのかな〜と感じています。

元々はCやC++のプロジェクトを自前でビルドする時に見かけた程度でしたが、まあ確かに仕組み的にはフロントエンドの環境構築にも応用できるので結構マッチするのかもですね。

cmkの実行タイミング

あまりメカニズムについて詳しく把握しているわけではないのですが、VSCodeがリアルタイムでHTMLとCSSを追従してくれてるっぽいので、ホットリロードみたいな仕組みを自前で用意する必要は無さそうです。

が、プロジェクトビルド時にはやはりgeneratedディレクトリを参照しているようなので、自分はビルドするタイミングでcmkを実行するように設定しています。

具体的にはこんな感じです。

generatedディレクトリの名前変更

CSS Modules Kitにはいくつかオプションの指定項目があり、その中に型定義の出力ディレクトリを変更するcmkOptions.dtsOutDirというオプションが存在します。

こんな感じで出力先を指定できます。 (出力先を変更した場合はcompilerOptionsで指定しているディレクトリパスも適宜変更してください)

AstroコンポーネントだとStylelintプラグインがバグる

Reactコンポーネントの場合は全く問題ないのですが、Astroコンポーネント用に書いているCSSファイルを開くとThe corresponding component file is not found (対応するコンポーネントファイルが見つかりません)と表示されてしまうバグが発生しています…。

内部実装を覗いてみると

となっていたのでここに.astroを追加してみても特に状況は変わらず、真相は闇の中です🙄

ちなみにこれだとCIが通らなくなってしまうので、Stylelintの設定ファイルにて

のようにして当該ルールを無効化しています🫠

この記事は 2025/08/12 02:38:48 にビルドされました