Edited at

webpackのcss-loaderでCSS Modulesをやる

More than 1 year has passed since last update.


はじめに

CSS Modulesの発想はよくわかったけど、具体的にどうやって導入したらいいかわかりにくく感じたので、webpackでCSS Modulesを使うための設定と、ReactでCSS Modulesを使う簡単な例を紹介します。

CSS Modulesの概要やいいところについてはこのあたりをどうぞ。

CSS Modulesを行うための方法はwebpack以外にもいくつかあるようです。

Browserify pluginのcss-modulesifyも人気そうです。(発音できない)


やってみる

まずは、必要なモジュールをインストールします。

CSS Modulesを使うために、style-loaderとcss-loaderが必要です。

React+babel+webpackの構成に必要なものも記述しています。

$ npm init -y

$ npm install --save react react-dom
$ npm install --save-dev webpack style-loader css-loader babel-loader babel-preset-es2015 babel-preset-react

次に、webpackの設定です。

loaders部分には、babel-loaderとCSS Modulesの二つが設定されています。

'css?modules'と書いてある部分が重要です。

modulesオプションを与えることで、css-loaderがCSS Modulesの振る舞いをするようになります。


webpack.config.js

module.exports = {

module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015'],
plugins: ['transform-react-jsx'],
},
},
{
test: /\.css$/,
loaders: ['style-loader', 'css-loader?modules'],
},
],
},
entry: './app',
output: {
path: __dirname,
filename: 'bundle.js',
},
resolve: {
extensions: ['', '.js', '.jsx'],
},
};


次に、CSSをこんな感じで書きます。。

CSSのクラス名は一般的にはhyphen-caseが多いような気がしますが、CSS Modulesの場合はJS側からアクセスしやすいようにcamelCaseにしておくと良さそうです。


app.css

.hogeHoge {

background-color: green;
}

最後に、Reactを使ったJS部分です。

app.cssをimport(またはrequire)することで、衝突しないように変換されたクラス名を読み込むことができます。

importした結果をdiv要素のclassNameに与えています。


app.jsx

import React from 'react';

import ReactDOM from 'react-dom';
import styles from './app.css'

class App extends React.Component {
render() {
return <div className={styles.hogeHoge}>hello</div>;
}
}

ReactDOM.render(<App/>, document.getElementById('content'));


一応HTMLも置いておきます。


index.html

<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8"/>
<title>CSS Modules Example</title>
</head>
<body>
<div id="content"></div>
<script src="bundle.js"></script>
</body>
</html>

以下のように適当にwebpackでビルドします。

私は普段はnpm scriptsに書いています。

$ ./node_modules/.bin/webpack

ブラウザでアクセスするとdivのクラス名が_3PdwrDVeQurTJpm2SrFLC2というように変換されていることが確認できると思います。

クラスの命名ルールはcss-loaderのlocalIdentNameオプションで変更することができます。

例えば、'css?modules&localIdentName=[path][name]---[local]---[hash:base64:5]'のように設定するとクラス名がapp---hogeHoge---3Pdwrのようになります。


おわりに

どうしてもSassを書きたくなかったので、これでBEM+Sassの代替手段として機能しそうです。