React.jsをビルドしてexternals利用

React.jsプロジェクトでは、webpackによるビルド時のデフォルト挙動がReact.jsライブラリ自体もビルドするため、時間がかかります。

そのため、externals指定してReact.jsをビルドから除外する手順が有効で、 React.js / ES2015向けwebpackビルド設定にまとめた通りです。

さらに一歩進んだ使い方として、別立てに切り出したReact.jsなどを1つのライブラリファイルとしてビルドする手があります。

たとえば、React.jsベースのUIライブラリ「Material-UI」は react-tap-event-pluginをあらかじめ組み込んでおく必要があるため、Reactを切り出すためにはReact / ReactDOM / react-tap-event-pluginをバンドルしたライブラリを1つ生成しておくことが求められます。

これは、以下のようにグローバル空間にrequireしていくだけのJavascriptファイルを作成すると作れます。

(この例では、Ajax通信用のsuperagentを追加し、react-tap-event-pluginの初期化処理も加えています)

window.ReactDOM = require('react-dom');
window.React = require("react");
window.request = require("superagent");

const injectTapEventPlugin = require('react-tap-event-plugin');
injectTapEventPlugin();

このファイルをビルドするためのwebpack.config.jsは以下のような記述になっています。この設定は1ファイルをビルドするだけの一般的な設定ととくに変わりはありません。

var webpack = require('webpack');
module.exports = {
  entry: {
    react_bundle: './src/bundle.js',
  },
  output: {
    path: __dirname + "/dist",
    filename: "[name].js"
  },
  resolve: {
    extensions: ['', '.js', 'jsx']
  },
  module: {
    loaders: [
      {
        test: /.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
        drop_console: true
      }
    })
  ]
};

このライブラリを利用するコンシューマー側のビルド設定では、React / ReactDOM / react-tap-event-plugin / superagentをexternalsに指定するだけです。

あとは、Reactコンポーネントを読み込むHTMLファイルで、今回のreact_bundle.js(ライブラリ塊)とコンシューマーのビルド済みJSの2つをscriptタグでインクルードすることで利用可能になります。

中馬崇尋
Chuma Takahiro