2番目にご紹介するのは、デザイナー/フロントエンドエンジニア柴田和祈によるセッション「CSS Modulesのベストプラクティスを探る」というタイトルで行われた発表の概要です。
なぜ、CSS Modulesを使うことにしたのか
現在は、Yahoo! JAPANの広告入稿管理ツールのフロントエンドを担当し、主にSPAを作っています。今回は、担当しているプロジェクトにCSS Modulesを活用した際の知見をお伝えしたいと思います。

まずCSSの問題点を考えてみると、スコープがグローバルであること、それを解決するためにBEMなどの手法を用いるとclass名が冗長になってしまうこと、などが挙げられます。
この問題解決のために、2014年にReactにおいて定評されたのがCSS in JS。CSSをJSのオブジェクトとして定義し、Component側からimportすることが可能で、JSファイルとしてCSSを管理するため、ローカルなスコープです。
しかし、classの重ねがけをするのにオブジェクトのマージが必要であったり、セレクタの優先度もないので、後からマージしたもの勝ちになる、疑似要素や:hoverなどが使えないなどといった課題がありました。
そこで登場したのが、CSSファイルをJSにimportすることができるCSS Modulesです。疑似要素や:hoverを使うことも可能で、プラグインで記法をカスタマイズすることもできます。

内部では何が起こっているのかというと…
JSからCSSをimportすることで、webpackのcss-loaderによって、最終的にHTMLの「head」タグ内の「style」としてインライン挿入されるようになります。
また、セレクタ名がBase64変換されるため、他のセレクタとかぶりを心配する必要がなくなり、webpack.config.jsで[ファイル名]_[クラス名]_[ランダム値]といったように形式を指定することもできるようになります。
このような形でCSSを定義して読み込むと、以下のようになります。


CSSの記法でBEMの良さを活かすには
BEMとは、Block(親)、Element(子)、Modifier(状態)を組み合わせて行うCSSの設計思想です。
BEMのルールに従い、Sassを使うと以下のようなCSSを吐き出すことができます。

これをCSS Modulesを使って、「ファイル名__クラス名___ランダム値」といった形で吐き出すとこのようなCSSが吐き出されます。

先頭のファイルとBlock名(.Nav)が重なって冗長なため、webpack.config.jsで「クラス名___ランダム値」という形式でCSSを吐き出したのが以下です。

しかし、実際にReact側で動かしてみると、Syntax Errorが出てしまいます。これはJSではハイフンを変数名として使えないから。そこで、modifierをアンスコ(_)に、ランダム値をハイフン(-)にしてみたところ、問題なくいけました。

さらに今度はBlock名も消してみたところ、冗長な部分もなくなり、Syntax Errorも出ず、React側も問題なくだいぶスッキリした状態になりました。

CSS Modulesのベストなディレクトリ構成は?
CSS Modulesのディレクトリ構成は何がベストなのか、考えてみました。一つ目の方法はコンポーネントの隣にCSSを置くこと。

同じ階層にCSSを配置するとかぶりがあり、冗長な部分が出てきてしまうため、共通部分を別CSSに切り出してみました。

上記のようにAlert.js / Submit.js両方からimportする方法もあるのですが、切り出したContainer.cssに対応するContainer.jsというコンポーネントを作ってあげるほうがよいのではないかと考えています。

CSSが共通化できるということは、コンポーネントも共通化できるはず。なぜならどちらもViewをつかさどっている部分なので、CSSができてJSのViewができないわけはないというのがその理由です。
二つ目の方法は、コンポーネントと同じ階層構造のディレクトリを作ること。

これはJSからimportする際に相対パスをたどるのが大変という点もあるのですが、同階層のパターンと比べて融通は効きやすいというメリットがあります。
結論としては、ディレクトリ階層は上記どちらでも良さそうということです。
* 当日資料「CSS Modulesのベストプラクティスを探る」はこちら