React x SCSS x Webpack開発環境セットアップ手順まとめ


スタイルシートをSCSSで、JSはES6で記述するReactJSのアプリケーションを、Webpackでビルドする手順についてまとめてみました。

スタイルシートはバンドルされたJSに含めず、ExtractTextWebpackPluginを利用してファイルを分けるようにしています。

この記事を試したnodeのバージョンは以下の通りです

$ node -v
v6.9.4
$ npm -v
3.10.10

プロジェクトの構成とnpmの初期化

プロジェクトのディレクトリ構成は以下のようにします

ディレクトリを作成

$ mkdir react-scss-webpack
$ cd react-scss-webpack
$ mkdir -p src/components
$ mkdir dist

npmの初期化

$ npm init -y

babel-loader のセットアップ

JSXのコンパイルはBabelを使います。

Babelは、ES2015(ES6) (またはそれ以降)からECMAScript5へのトランスパイルに加えて、JSXも扱えます。

Webpackでは、babel-loader からBabelを利用します。
参考: Using Babel · Babel

Reactのインストール

InstallationのAdding React to an Existing Applicationを参考に

$ npm install --save react react-dom

babel-loaderのインストール

babel-loaderを参考に以下のパッケージをインストール
babel-preset-envの替わりに、JSXをコンパイルするためにbabel-preset-reactを入れている

$ npm install --save-dev babel-loader babel-core babel-preset-react webpack

IE11に対応が必要ないなど、ECMAScript5に変換する必要が場合は、webpack自体がES6のモジュールシステムを解釈できるのでbabel-preset-es2015は無くても大丈夫です

webpack.config.js

.babelrcを利用しないでoptionspresetsを指定する場合、webpack.config.jsは以下のようになります

// webpack.config.js
const path = require('path');
module.exports = {
  entry: './src/index.jsx',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.jsx$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['react']
          }
        }
      }
    ]
  }
};

Hello World

Hello World – ReactHello Worldを表示するコンポーネントを分割して以下のように記述、配置します

// src/components/Hello.jsx
import React from 'react';

export const Hello = (<h1>Hello, world!</h1>);

Helloを読み込むエントリファイル

import ReactDOM from 'react-dom';

import {Hello} from './components/Hello.jsx'

console.log(Hello);
ReactDOM.render(
  Hello,
  document.getElementById('root')
);

バンドルされたソースを読み込むindex.htmlは以下のように記述します

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
  </head>
  <body>
    <div id="root"></div>

    <script src="./dist/bundle.js"></script>
  </body>
</html>

ビルドして動作を確認

Webpackは、ローカルインストールしたので以下のコマンドで実行します

$ ./node_modules/webpack/bin/webpack.js

index.htmlを開くと

$ open index.html

このように表示されました

ここまでで、BabelをでJSXをコンパイルする環境が整いました

sass-loaderのセットアップ

次に、SCSSでスタイルシートを書いてWebpackでコンパイルしてみます。

Webpackのドキュメント Loading CSS | Asset Management、および、sass-loaderあたりを参考にセットアップします

style-loader,css-loader,sass-loaderのインストール

node-sassは、sass-loaderpeerDependenciesパッケージなので明示的にインストールします

$ npm install style-loader css-loader sass-loader node-sass --save-dev

webpack.config.js

babel-loaderのRuelの後に、sass-loaderのRuleを追加します

// webpack.config.js
module.exports = {
  // ...
  module: {
    rules: [
      {
        // ... babel-loaderを呼び出すRule
      },
      {
        test: /\.scss$/,
        use: [{
          loader: "style-loader" // creates style nodes from JS strings
        }, {
          loader: "css-loader" // translates CSS into CommonJS
        }, {
          loader: "sass-loader" // compiles Sass to CSS
        }]
      }
    ]
  }
};

SCSSの追加とスタイルの適用

Hello World!の文字色を赤くするSCSSを追加します

// src/components/Hello.scss
$header-color: red !default;

h1 {
  color: $header-color;
}

Hello.jsxで読み込みます

import React from 'react';
import "./Hello.scss"

export const Hello = (<h1>Hello, world!</h1>);

ビルドして動作を確認

webpackコマンドを実行してブラウザで確認しています

$ ./node_modules/webpack/bin/webpack.js
$ open index.html

文字が赤くなったことを確認できます

ExtractTextWebpackPluginのセットアップ

上記のsass-loaderの設定では、以下のように、bundle.jsが読み込れた後に、Javascriptでsytleタグが追加されます

次に、ExtractTextWebpackPluginを利用してスタイルシートを分割し、linkタグで読み込めるようにしていきます

ExtractTextWebpackPluginのインストール

# npm install --save-dev extract-text-webpack-plugin

webpack.config.js

ExtractTextWebpackPluginのドキュメントのExtracting Sass or LESSを参考にwebpack.config.jsを以下のように修正します

// webpack.config.js
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  // ...
  module: {
    rules: [
      {
        // ... babel-loaderを呼び出すRule
      },
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: ['css-loader', 'sass-loader']
        })
      }
    ],
  },
  plugins: [
    new ExtractTextPlugin("styles.css"),
  ]
};

サンプルに適用

index.htmlにlinkタグを追加します

// index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <link href="./dist/styles.css" rel="stylesheet">
  </head>
  <body>
    <div id="root"></div>

    <script src="./dist/bundle.js"></script>
  </body>
</html>

webpackを実行して確認すると先ほどと同じように表示されます

参考

Setting Up a React.js Environment Using Npm, Babel 6 and Webpack
Getting Started with React and JSX
Babelで始める!モダンJavaScript開発 | HTML5Experts.jp

, , ,