maesblog

Reactを「webpack + babel-loader」でビルドする方法

自分はReactのビルドにBrowserifyを主に使用しており、昨年には『Reactをnpmでビルドする方法 browserify (watchify) + babelify編』という記事も書きました。ただ、ここ最近のwebpackの人気っぷりはすさまじいものがあり、「React + webpack」という組み合わせが今後のスタンダードになってもおかしくないという状況なので、今回はwebpackでReactをビルドする方法をまとめてみました。

webpackとは

webpack_module_bundler

webpackは、browserifyと同様、複数のファイルの依存関係を顧慮してビルドを行うツールです。Browserifyとの大きな違いは、対象となるのがJSファイルだけでなく、CSSファイルや画像などに及ぶというところでしょうか。また最終的に生成するファイルも複数にわけることもできたりします。プラグインがすでに含まれていたり、高機能なことは間違いないです。

詳細はwebpackのサイトを見てください。

そして注目すべきは、その人気っぷりです。以下は「webpack」「browserify」Google Trendsでの比較結果です。2014年の後半から現在に至るまでうなぎ登り状態です。

webpack vs Browserify 検索数の比較

webpackは、Reactの開発においてその使用が推奨されています。Reactもv0.14の頃から「npm経由で使用し、browserifyやwebpackのようなツールを使ってコードを一つのバンドルの中にビルドする」といった開発方法が大きくアナウンスされるようになりました。

ということで、以下よりwebpackを使ったReactのビルド環境の構築方法を説明していきます。npm => React => webpackといった流れで説明していきます。すでにわかっているところがあれば飛ばして次に進んじゃってください。

npm環境の準備

まずはReactの開発を進めていくためのワーキングディレクトリを作成します。

$ mkdir hello-react

作成したディレクトリに移動して、npm initのコマンドを実行するとディレクトリ内にpackage.jsonファイルが作られ、プロジェクトのディレクトリ内でnpmが使用できるようになります。

$ cd hello-react
$ npm init

npmはNode.jsのパッケージ管理ツールです。npmを使用するには、Node.jsがインストールされている必要があります。Node.jsのインストールをまだしてない方は、当ブログの以下の記事などを参考にしてインストールしてください。

Reactの開発に必要なファイルの準備

今回の説明では以下の3つのファイルを使用します。

  • app.jsx: 実際にReactでコンポーネントを書くファイル
  • bundle.js: app.jsのコンパイル先で、index.htmlで読み込むためのファイル
  • index.html: bundle.jsを読み込んでReactコンポーネントがレンダリングされるReactアプリケーション本体となるファイル

上記のファイルを以下のようなディレクトリ構成で作成します。

hello-react/
│
├─ src/
│   └─ app.jsx
│
├─ dist/
│   └─ bundle.js
│
└─ index.html

作成したindex.htmlファイルには、以下のように記述しておきます。後ほどコンパイルしたReactのコンポーネント(bundle.js)をこのhtmlファイルで読み込みます。

<!doctype html>

<html>

<head>
  <meta charset="utf-8">
  <title>Hello React</title>
</head>

<body>
  <div class="content"></div>
  <script src="./dist/bundle.js"></script>
</body>

</html>
index.html

Reactでコンポーネントを作る

ファイルの準備が整ったら、いよいよReactをインストールし、実際にReactのコンポーネントを作っていきます。

Reactをインストールする

Reactのコンポーネントを作成するには、reactreact-domという2つのパッケージが必要です。以下のコマンドでインストールします。

$ npm install --save react react-dom

インストールしたパッケージの読み込み

インストールしたreactとreact-domを、Node.jsのrequire()メソッドを使って、開発用に作成したapp.jsxファイルに読み込みます。ファイルの先頭に以下を記述します。

var React = require('react');
var ReactDOM = require('react-dom');
app.jsx

ES2015のimportを使って読み込む場合は、以下のように書きます。

import React from 'react';
import ReactDOM from 'react-dom';
app.jsx

Reactのコンポーネントを書く

Reactをファイルに読み込んだら、さっそくReactのコンポーネントを書いていきましょう。今回は単純に「Hello React!!」を表示させるだけのコンポーネントとします。それからES2015構文ではなく一般的なJavaScript(ES5)構文で書きます。

var React = require('react');
var ReactDOM = require('react-dom');

// コンポーネント名の頭文字は大文字にする
var HelloReact = React.createClass({
  render: function () {
    return (
      <div>
        Hello React!!
      </div>
    );
  }
});

ReactDOM.render(
  <HelloReact />,
  document.querySelector(".content")
);
app.jsx

Reactに関しては、ここでは詳しく書きません。Reactでの実装に関する詳細はチュートリアルを参考にすると良いでしょう。当ブログでは本家サイトのチュートリアルを日本語に訳した記事を投稿していますので、併せてご確認ください。

webpackを使ってビルド環境を構築する

上記でReactのコンポーネントのコードを記述したapp.jsxは、reactやreact-domといったパッケージを読み込んでいたり、JSXという特集な構文を使って書いてあったりするので、ブラウザでは直接開けません。つまりブラウザで内容を確認することができません。

そこでブラウザでも読める「素のJavaScript(ES5)」に変換するためのビルド環境を構築してあげる必要があります。そこでwebpackの登場です。以下よりwebpackを使ったビルド環境の構築方法を説明していきます。

ちなみに、ビルド環境はwebpack以外でも準備することができます。webpack以外でよく使われているのが、browserifyとなります。browserifyを使ったビルド環境の構築方法については、当ブログの以下の記事をご参照ください。

webpackをインストールする

webpackはnpm(Node.jsのパッケージ管理ツール)経由でインストールします。(npmを使用するには上記でも説明した通り、Node.jsが必要となります。)

まずwebpackをグローバル(システム上)にインストールします。webpackコマンドが使えるようになります。ただし、グローバル版は必須ではないので、webpackコマンドを使わないのであれば、インストールしなくてもよいです。

$ npm install -g webpack

次にプロジェクトディレクトリにwebpackをインストールします。

$ npm install --save-dev webpack

webpackのインストールの詳細については、以下をご参照ください。

Babel環境の準備

上で書いたように、ReactはHTMLのようなJSXという特殊な構文を使ってコンポーネントのDOMの部分を書くことができます。従って、このJSXもブラウザで読める形にコンパイルしてあげる必要があります。

そこでBabelを使用してJSXをコンパイルします。ES2015のコンパイラとして有名なBabelですが、JSXのコンパイルにも使えます。webpackのloaderにも「babel-loader」というパッケージがあります。webpackのタスクとしてbabel-loaderを使用して、JSXのコンパイルを行うようにします。

babel-loaderのインストール

まず以下のコマンドで、「babel-loader」と、peerDependenciesとなっている「babel-core」をインストールします。

$ npm install --save-dev babel-loader babel-core

Babelのプリセットのインストール

babel-loaderでJSXのコンパイルが行えるようにするためにBabelのpresetである「babel-preset-react」をインストールします。

$ npm install --save-dev babel-preset-react

ReactのコンポーネントをES2015の構文で書く場合は、さらにES2015のコンパイル用のpreset「babel-preset-es2015」をインストールします。

$ npm install --save-dev babel-preset-es2015

.babelrcファイルの設定

Babelの実行時に使用するpresetを指定するための設定ファイル.babelrcをプロジェクトディレクトリ内に作成します。

$ touch .babelrc

.babelrcファイルを作成したら、以下のように記述します。これでインストールしたpreset「babel-preset-react」が適用されます。

{
  "presets": ["react"]
}
.babelrc

さらに「babel-preset-2015」を使用したES2015のコンパイルにも対応させるには、以下のように記述します。

{
  "presets": ["react", "es2015"]
}
.babelrc

Reactをビルドする

Babelの環境が整ったら、最後にwebpackの設定を行います。その設定内容に基づいてReactのビルドを行います。

設定ファイルの準備

webpackで使用する設定ファイルは、「webpack.config.js」となります。プロジェクトディレクトリ内にwebpack.config.jsファイルを作成します。

$ touch webpack.config.js

webpack.config.jsファイルを作成したら、以下のように記述します。(記述内容についてはソース内のコメントを参照してください。)

module.exports = {
  /* ビルドの起点となるファイルの設定 */
  entry: './src/app.jsx',
  /* 出力されるファイルの設定 */
  output: {
    path: './dist', // 出力先のパス
    filename: 'bundle.js' // 出力先のファイル名
  },
  /* ソースマップをファイル内に出力させる場合は以下を追加 */
  devtool: 'inline-source-map',
  module: {
    /* loaderの設定 */
    loaders: [
      {
        test: /\.(js|jsx)$/, // 対象となるファイルの拡張子(正規表現可)
        exclude: /node_modules/, // 除外するファイル/ディレクトリ(正規表現可)
        loader: 'babel-loader' // 使用するloader
      }
    ]
  }
};
webpack.config.js

npmコマンドへの登録

webpackコマンドを直接叩いてもよいですが、毎回コマンドにオプションなどをつけて実行するのは大変です。今回は、npm runコマンドを使用してファイルをビルドする方法を紹介します。(多少楽になります。)

npm runコマンドを使用してwebpackを実行させるには、package.json“scirpts”フィールドの値の部分に、実行させたいwebpackコマンドを記述します。

webpackコマンドを、package.jsonに以下のように記述します。オプションとしてwatchを指定すると、ファイルの更新を監視するようになります。

{
  ...
  "scripts": {
    "watch": "webpack --watch --progress"
  },
  ...
}
package.json

上記のコマンドでは、watchオプションの他に、progressオプションを指定しています。これはwebpackのビルド状況を表示させるためのオプションとなります。このようにwebpackのコマンドには豊富なオプションが用意されています。コマンドやそのオプションについては以下を参照してください。

webpackの実行

以下のコマンドを実行すると、app.jsxファイルを更新するたびにwebpackが実行され、bundle.jsファイルにビルドされるようになります。

$ npm run watch

以下のコマンドでindex.htmlファイルをブラウザで開き、Reactの開発状況を確認します。

$ open index.html

製品版としてビルドする

開発が一通り終わると、最終的に製品版としてビルドすることになります。Reactはデフォルトでは、ディペロップメント(開発者)モードになっていて、余計な情報が含まれています。開発時には必要なこれらの情報も、製品版には必要ありません。そこで、製品版としてビルドする際は、これらの情報を含まないようにしてあげる必要があります。そうすることで、アプリケーション自体の高速化も実現できます。

まずは製品版としてビルドする際の設定方法を紹介していきます。この設定によって何がなされるかは後ほど説明します。

設定ファイルの準備

製品版のビルド専用の設定ファイルを新たに作ります。今回は通常の設定ファイルと区別するために「webpack-production.config.js」といった任意のファイル名をつけておきます。

$ touch webpack-production.config.js

webpack-production.config.jsファイルを作成したら、以下のように記述します。上で説明したwebpack.config.jsファイルに追記する感じとなります。(記述内容についてはソース内のコメントを参照してください。)

/* webpackを読み込みます */
var webpack = require('webpack');

module.exports = {
  entry: './src/app.jsx',
  output: {
    path: './dist',
    filename: 'bundle.js' // ファイル名は適宜変更してください
  },
  module: {
    loaders: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      }
    ]
  },
  /* プラグインの設定 */
  plugins: [
    /* DefinePluginの実行 */
    new webpack.DefinePlugin({
      // process.env.NODE_ENVを'production'に置き換える
      'process.env.NODE_ENV': JSON.stringify('production')
    }),
    /* UglifyJsPluginの実行 */
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        // 圧縮する時に警告を除去する
        warnings: false
      }
    })
  ]
};
webpack-production.config.js

ここでやっていることは、UglifyJsPluginでコードを圧縮/最適化する際に除去したいデバッグコードをDefinePluginを使って指定するといったことになります。DefinePlugin、UglifyJsPluginの詳細については以下をご参照ください。

npmコマンドへの登録

製品版のビルド用のwebpackコマンドもnpm scriptとしてpackage.jsonファイルに登録しておきます。 webpack-production.config.jsという設定ファイルを別に作成したので、configオプションを使って、参照する設定ファイルを指定するようにします。ファイル更新の監視をする必要はないので、watchオプションは外しておきます。

{
  ...
  "scripts": {
    "watch": "webpack --watch --progress",
    "build": "webpack --config webpack-production.config.js --progress"
  },
  ...
}
package.json

webpackの実行

以下のコマンドを実行すると、製品版としてbundle.jsファイルにビルドされます。

$ npm run build

製品版の内容を確認する場合、以下のコマンドでindex.htmlをブラウザで開いて確認します。「Hello React!!」と表示されれば完了です。

$ open index.html

実際の処理について

Reactのコードは、Developmentモードの時だけ表示させたい部分を以下のように記述しています。

if (process.env.NODE_ENV !== 'production') {
  console.log('development only')
}

webpack.DefinePluginにより、process.env.NODE_ENVの部分が‘production’に置き換えられます。

if ('production' !== 'production') {
  console.log('development only')
}

最終的にwebpack.optimize.UglifyJsPluginでコードの最適化を行う際に、以下の部分がすべて不要なコードとして削除されます。

if ('production' !== 'production') {
  console.log('development only')
}

まとめ

けっこうなボリュームの記事となりました。やらなくてはいけない作業が多く、開発環境構築も慣れていないと最初は大変だと思います。ただ、一度環境の構築が完了してしまえば、あとは開発に集中できるようになるので、がんばってみてください。

webpackはbrowserifyとよく比較されますが、正直Reactの開発においてはどっちがいい悪いというのはないかなと思っています。好みの問題かなと思います。自分の感想としては、webpackは最初から多くのプラグインが同梱されていて高機能なため、設定にやや癖があるかなといったところです。設定ファイルの書き方とか、覚えるのが最初は大変かなと思います。

一番最初でも触れたようにBrowserifyを使ったビルド環境の構築方法についての記事も書いてますので、それぞれお試しいただければと思います。

それから、当記事で暑かったサンプルをGitHub上に置いておきましたので、git cloneでもして内容をご確認ください。

入門 React ―コンポーネントベースのWebフロントエンド開発
  • 『入門 React ―コンポーネントベースのWebフロントエンド開発』
  • 著者: Frankie Bagnardi, Jonathan Beebe, Richard Feldman, Tom Hallett, Simon HØjberg, Karl Mikkelsen, 宮崎 空(翻訳)
  • 出版社: オライリージャパン
  • 発売日: 2015年4月3日
  • ISBN: 978-4873117195

関連記事

コメント

    • 必須

    コメント