React+WebpackでSassを使えるようにする手順

# はじめに

React+Webpackの開発環境にSassを導入しました。
今回はWebpackでSassをビルドする環境を構築する手順を説明します。
なお、今回はSassを導入する開発環境の雛形として[用語解説から丁寧に。yarnでwebpack-dev-server+Babel+React(JSX)な開発環境構築手順](https://qiita.com/nishina555/items/b2aac6326d6a8ed6753f)で説明したものを利用します。

# ディレクトリ構成

今回作成する開発環境は以下のようなディレクトリ構成になっております。

```
├── dist
│   ├── bundle.js
│   ├── style.js
│   └── index.html
├── node_modules
├── package.json
├── src
│   ├── Hello.jsx
│   └── index.jsx
├── stylesheets
│   └── style.scss
├── webpack.config.js
└── yarn.lock
```


# 必要なパッケージのインストール

まず必要なパッケージをインストールします。
インストールするパッケージについてざっくりと説明をすると、ローダーはCSSをJavaScript上で読み込めるようにする役割、extract-text-webpack-pluginは読み込み可能となったCSSを実際のCSSファイルに変換する役割をします。
このあたりの内容については[なんとなくで理解しないWebpackのCSS周辺](https://qiita.com/inuscript/items/0574ab1ef358fecb55b9)の記事がとてもわかりやすいです。

```bash
$ yarn add --dev extract-text-webpack-plugin node-sass style-loader css-loader sass-loader
```

package.jsonを確認すると以下の行が追加されていることがわかります。


```diff:package.json
{
  "name": "react-webpack-sample",
  "version": "1.0.0",
  "description": "sample application for react with webpack",
  "main": "index.js",
  "author": "nishina555",
  "license": "MIT",
  "dependencies": {
    "react": "^16.1.0",
    "react-dom": "^16.1.0"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
+   "css-loader": "^0.28.7",
+   "extract-text-webpack-plugin": "^3.0.2",
+   "node-sass": "^4.6.0",
+   "sass-loader": "^6.0.6",
+   "style-loader": "^0.19.0",
    "webpack": "^3.8.1",
    "webpack-dev-server": "^2.9.4"
  }
}
```

# Webpackの設定

webpack.config.jsに以下の内容を追加します。
今回は`stylesheets/style.scss`を`dist/style.css`に変換するという設定を行なっています。
記述方法については[extract-text-webpack-pluginのリポジトリ](https://github.com/webpack-contrib/extract-text-webpack-plugin)に書いてあるのでそれを参考に記述していきます。


```diff:webpack.config.js
  const path = require('path');
+ const ExtractTextPlugin = require('extract-text-webpack-plugin');

  module.exports = [
    {
      entry: __dirname + "/src/index.jsx", // トランスパイル対象
      output: {
        path: __dirname + '/dist', // 出力先ディレクトリ
        filename: 'bundle.js' // 入力されたファイルをまとめて出力するときのファイル名
      },
      module: {
        rules: [
          {
            test: /\.js[x]?$/,
            exclude: /node_modules/,
            loader: "babel-loader", // Babelをwebpackで利用できるようにする
            options:{
              presets: ['react', 'es2015'] // reactとes2015をトランスパイル対象とする
            }
          },
        ]
      },
      devServer: {
        contentBase: path.resolve(__dirname, "dist"), // distディレクトリのファイルを確認する
        port: 3000, // 3000ポートを利用
      },
      resolve: {
        extensions: ['.js', '.jsx'] // jsファイル, jsxファイルを対象とする
      }
    },
+    {
+      entry: {
+        style: __dirname + "/stylesheets/style.scss", // トランスパイル対象
+      },
+      output: {
+        path: __dirname + '/dist', // 出力先ディレクトリ
+        filename: '[name].css'
+      },
+      module: {
+        rules: [
+          {
+            test: /\.scss$/,
+            loader: ExtractTextPlugin.extract({
+              fallback: 'style-loader',
+              use: ['css-loader', 'sass-loader']
+            })
+          }
+        ]
+      },
+      plugins: [
+        new ExtractTextPlugin('[name].css'),
+      ],
+    },
  ];

```



# サンプルの作成

次にサンプルを作成します。
まず、stylesheetsディレクトリを作成しそこにscssファイルを作成します。

```stylesheets/style.scss
$red: #FF3333;
h1 {
  color: $red;
}

```

この状態でwebpackを実行するとdistディレクトリにcssファイルが作成されることがわかります。(この作業は動作確認をする上で行わなくても問題ありません。)

```bash
$ ./node_modules/.bin/webpack
$ ls dist
bundle.js  index.html style.css
```

次にindex.htmlに以下の項目を追加します。
これでwebpackでコンパイルされたcssファイルを読み込むことができます。

```diff:index.html
<!DOCTYPE html>
<html><head>
  <title>react-webpack-sample</title>
  <meta charset="utf-8">
+  <link rel="stylesheet" href="style.css">
</head>
  <body>
    <div id="root"></div>
    <script src="bundle.js"></script>
  </body>
</html>
```

# 動作確認

webpack-dev-serverを起動をし、scssが正しく反映されているか確認します。

```
$ ./node_modules/.bin/webpack-dev-server
```

http://localhost:3000/ にアクセスをして以下のようになっていればOKです。

![スクリーンショット 2017-11-12 6.26.19.png](https://qiita-image-store.s3.amazonaws.com/0/140792/9629b47c-adb2-b9a5-bbc0-fecdbb0648ae.png)