スタイルシートを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
を利用しないでoptions
にpresets
を指定する場合、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 – ReactのHello 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-loader
のpeerDependencies
パッケージなので明示的にインストールします
$ 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