React.js / ES2015向けwebpackビルド設定

ES2015やReact.jsでWebアプリ開発する場合、Babelやwebpack(またはbrowserify)などのツールチェーンが不可欠です。

事実上、開発に入る前にビルド環境は構築し切っておく必要があります。

手法はいくつかあるのですが、今回はwebpackを用いた最低限の設定例を解説します。

Webpackの設定

本番環境用と開発環境用の2系統のビルド設定ファイルを用意します。

基本的な設定は共通ですが、デバッグ情報の付加設定などに違いがあります。

開発環境用 webpack設定

var webpack = require('webpack');
module.exports = {
  entry: {
    app: './src/app.jsx',
  },
  output: {
    path: __dirname + "/build-dev",
    filename: "[name].js"
  },
  resolve: {
    extensions: ['', '.js', 'jsx']
  },
  module: {
    loaders: [
      {
        test: /.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  },
    externals: {
               'react': 'React',
               'react-dom': 'ReactDOM',
           },
  plugins: [
  ]
};

本番環境用 webpack設定

var webpack = require('webpack');
module.exports = {
  entry: {
    app: './src/app.jsx',
  },
  output: {
    path: __dirname + "/build-prod",
    filename: "[name].js"
  },
  resolve: {
    extensions: ['', '.js', 'jsx']
  },
  module: {
    loaders: [
      {
        test: /.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  },
  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM',
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    new webpack.optimize.UglifyJsPlugin()
  ]
};

主な違いは以下の点です。

  • 開発用(build-dev)と本番用(build-prod)の出力ディレクトリを切り分け
  • 本番環境用は、React.jsからデバッグ情報を除去するためNODE_ENVを設定
  • 本番環境用は、コードを圧縮するためUglifyJsPluginを指定

出力ディレクトリはあらかじめmkdirしておく必要があります。

また、React.jsじたいの本番環境用設定は、webpack -pではなく、NODE_ENVで指定する点は注意が必要です。

webpackがビルド済みファイルを作成する際に、React.jsそのものも1ファイルに組み込むため、ライブラリのコードも最適化が求められるものです。

ただし、今回の設定例では、ReactとReactDOMをexternals指定していてビルド対象から除外しているため、実際にはNODE_ENVを指定する必要はないかもしれません。

externalsに関する補足

externalsに設定したライブラリは、 CDNなどを利用して、別途HTMLから読み込む必要があります。

ライブラリを外部読み込み指定しているのは、1ページ内に2つ以上のJS機能を組み込むような用途で、前提ライブラリが重複すると干渉するからです。

また、externals指定したライブラリはwebpackによる変換処理を通過しないため、ビルドにかかる時間も短縮できます。

npm script

webpack.config.jsを2系統用意したため、ビルドコマンドにも開発環境用と本番環境用のオプションを使い分ける必要があります。

npmスクリプトに設定しておくことで、オプションに分かりやすいエイリアスを準備できます。

以下のpackage.jsonの設定例では、npm run build-dev(開発用)とnpm run build-prod(本番用)を定義しています。

なお、npmスクリプトは引数を指定できるため、たとえばファイル更新をWatchするモード(-wオプション)で動作させたい場合npm run build-dev -- -wのように起動します。

{
  "name": "react-build-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build-dev": "webpack --config webpack.config.dev.js",
    "build-prod": "webpack -p --config webpack.config.prod.js",
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.10.4",
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.5.0",
    "webpack": "^1.13.1"
  },
  "dependencies": {
    "react": "^15.1",
    "react-dom": "^15.1"
  }
}

build-prodに-pオプションを指定しているのは、webpackの標準機能でminifyするためです。これにより、–optimize-minimize–optimize-occurence-orderが指定されるようです。

ただし、-pオプションは包括的な最適化指定ではなく、先ほどのReact.jsの最適化や、 Uglifyなどは別途指定する必要があります。

中馬崇尋
Chuma Takahiro