CSS ModulesをStorybookで適用するために必要なwebpackの設定
ReactやVueを使っているとCSS Modulesでコンポーネントのスタイルを適用するがあります。
CSS Modulesを使うことで1つのコンポーネントに対して1つのスタイルシートを適用でき、ローカルスコープが適用できたりするので、とても便利です。
そんな便利なCSS Modulesですが、Storybookを使うときには注意が必要です。
webpackの設定で適切なオプションを記述しておかないと、スタイルが当たらない状態になってしまいます。
Storybookのcss-loaderオプションを設定する
まずStorybookでもCSS Modulesを使ったスタイル指定が動くwebpackの設定が下記です。
このコードはStorybookのissueでコメントされていたものです。
module.exports = async ({ config, mode }) => {
config.module.rules.push({
test: /\.scss$/,
loaders: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: {
mode: 'local',
localIdentName: '[path][name]__[local]--[hash:base64:5]',
context: path.resolve(__dirname, 'src'),
hashPrefix: 'my-custom-hash',
},
},
},
require.resolve('sass-loader')
],
});
return config;
}
今回重要になるのはcss-loaderの部分です。
css-loaderのオプション
指定しているオプションを順番にみていきます。
css-loaderのオプションについてはwebpackの公式で説明があります。
それぞれのオプションを日本語訳にかけてみました。
importLoaders
タイプ:数値デフォルト:0
CSSローダーの前に適用されるローダーの数を有効/無効または設定します。
オプションimportLoadersを使用すると、css-loaderを@importedリソースに適用する前にローダーの数を構成できます。
modules.mode
タイプ:文字列|関数デフォルト: 'local'
セットアップモードオプション。 ローカルモードが必要な場合は、値を省略できます。
ストリング
可能な値-ローカル、グローバル、および純粋。
modules.localIdentName
タイプ:文字列デフォルト: '[hash:base64]'
生成されたIDは、localIdentNameクエリパラメータで構成できます。 オプションの詳細については、loader-utilsのドキュメントを参照してください。
推奨事項:
開発には「[パス] [名前] __ [ローカル]」を使用
本番には「[hash:base64]」を使用
[local]プレースホルダーには、元のクラスが含まれています。注:予約済みおよび制御ファイルシステムの文字([local]プレースホルダー内の文字を除く)はすべて-に変換されます。
modules.context
タイプ:文字列デフォルト:未定義
ローカルID名の基本ローダーコンテキストを再定義できます。 デフォルトではローダーのrootContextを使用します。
modules.hashPrefix
タイプ:文字列デフォルト:未定義
カスタムハッシュを追加して、よりユニークなクラスを生成できるようにします。
まとめ
Storybookはwebpackの設定を個別に設定する必要があるのでハマりがちです。
フレームワークを使っていると内部でよしなにやってくれている場合なんかだと、アプリは動いているのにStorybookでは正しく動いてくれない・・。
こういうときは大体Storybookのwebpackの設定を見直すことで解決できることが大半です。
今回のようにstorybookでCSS Modulesを使うにはcss-loaderの設定が必要ということを頭に置いておくと良いと思います。
Discussion