webpackとbowerを使ってreact.jsを読み込みgulpでビルドする

##はじめに
webpackが流行ってきているようなので、がんばって使ってみます。
流れが早すぎておじさんには辛いです。

せっかくwebpackを使うのでreact.jsを使ってみます。
こちらもはじめて。

##webpackとは
jsの依存関係を解決して、複数のjsファイルを1つに結合してくれるビルドツールです。
大規模なアプリケーションを開発する際に、力を発揮しそうです。

####◎gulpなどで結合するのとの違い
gulpなどでjsファイルを結合する際は、読み込み順を気にする必要がありますが、
webpackの場合、requireした箇所でモジュールを読み込んでくれるので順番を気にする必要が無いようです。

##webpackを使ってみる

####◎webpackをインストール
```
sudo npm install webpack -g
```

####◎ファイル構成

```
.
└── www
    ├── index.html
    └── js
        ├── main.js
        └── sub.js
```



```lang:main.js
var sub = require('./sub');
sub('test');
```


```lang:sub.js
module.exports = function(s) {
     alert(s);
};
```

```lang:index.html
<body>
   <script src="./dist/bundle.js"></script>
</body>

```

下記コマンドを実行
```
//webpack <input> <output>
$ webpack www/js/main.js www/dist/bundle.js
```
www配下にdist/bundle.jsが作成されます。

index.htmlをブラウザで開くとアラートが表示されます。

##webpack.config.jsを使う
毎回コマンドを打つのは初心者の私には辛いので
設定ファイル（webpack.config.js）を使います。

webpackコマンド実行時のディレクトリ内に、webpack.config.jsがあった場合自動的に読み込んでくれます。

```lang:webpack.config.js
module.exports = {
    entry: './www/js/main.js',
    output: {
        path:__dirname + '/www/dist/',
        filename: 'bundle.js'
    }
}
```
```
$ webpack
```
bundle.jsがwww/dist/配下に作成されます。


##bowerと連携する

react.jsなど必要なライブラリをbowerに管理します。
webpackと連携するには少しだけ手間が必要です。

公式サイトの情報はこちら
><a href="http://webpack.github.io/docs/usage-with-bower.html" target="_blank">USAGE WITH BOWER</a>

```
var path = require("path");
var webpack = require("webpack");
module.exports = {
    resolve: {
        root: [path.join(__dirname, "bower_components")]
    },
    plugins: [
        new webpack.ResolverPlugin(
            new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
        )
    ]
}
```
ただし上記の方法だが、少し問題があり、
```ResolverPlugin.DirectoryDescriptionFilePlugin```を使用すると読み込むライブラリのbower.jsonの**mainが配列**の場合読み込めなくなる。

####◎解決方法
<a href="https://github.com/lpiepiora/bower-webpack-plugin" target="_blank">bower-webpack-plugin</a>を使用する。
これでmainが配列の場合も問題なく読み込むことができる。

```
var BowerWebpackPlugin = require("bower-webpack-plugin");
module.exports = {
   plugins: [new BowerWebpackPlugin()]
}
```

##gulpを使ってビルドする。
gulpタスクの中でwebpackを使うには```gulp-webpack```が必要です。
gulp-webpackをまずはインストールします。

>####追記
<a href="http://qiita.com/naru0504" target="_blank">naru0504<a/>さんよりコメント頂ましたので修正点追記します。

>- gulp-webpackは最新版は**webpack-stream**と名前を変えている。
gulp-webpackだとビルドした際にwarningがでるのでwebpack-streamに移行したほうがよい。

webpackを実行する。設定はwebpack.config.jsを利用。

```
$ npm install gulp-webpack --save-dev
```
```lang:gulpfile.js

var gulp = require('gulp');
var webpack = require('gulp-webpack');
var webpackConfig = require('./webpack.config.js');

gulp.task('build', function() {
    return gulp.src('')
        .pipe(webpack(webpackConfig))
        .pipe(gulp.dest('.www/dist/'));
});
```

これで```gulp build```でwebpackを実行できるようになりました。

##react.jsを使う

####◎ファイル構成
```
.
├── bower.json
├── bower_components
├── gulpfile.js
├── node_modules
├── package.json
├── webpack.config.js
└── www
    ├── index.html
    └── js
        └── main.jsx
```

####◎jsx-loaderをインストール
webpackで、JSXをコンパイルするには。***jsx-loader***が必要となる為、インストールします。

```
$ npm install jsx-loader --save-dev
```

webpack.confing.jsのmodule.loadersで、jsx-loaderを読み込む。

```lang:webpack.confing.js
 module.exports = {
     entry: {
     bundle:'./www/js/main.jsx'
     },
     output: {
         path: __dirname + '/www/dist/',
         filename: '[name].js'
     },
     module: {
         loaders: [{
             test: /\.jsx$/,
             loader: 'jsx-loader?harmony'
         }]
     },
     //externals: {
     //    'react': 'React'//html側でreact.jsを読み込んでいる場合は必要
     //},
     resolve: {
         extensions: ['', '.js', '.jsx'],
     }
 };
```

####補足
#####①harmonyオプション
***loader: 'jsx-loader?harmony'***のharmonyオプションを追加することで、ES6の仕様の一部を使うことができるようになります。

#####②externals
詳しくは下記を参照
><a href="http://yokotakenji.me/log/programming/js/webpack/4315/#externals" target="_blank">webpackのconfiguration#externals</a>
>webpackによって解決されるべきではない依存関係を指定しますが、生成されたバンドルの依存関係になります。

よく意味がわからなかったが、webpackのコンパイルに含めないものを定義するようです。
例えば、react.jsをhtml側ですでに読み込んでいる場合、ビルドに含める必要がないのでexternalsに追加します。

####◎react.jsをインストール

```
 bower install react --save-dev
```

```lang:index.html
<body>
    <div id="content"></div>
    <script src="./dist/main.js"></script>
</body>

```

```main.jsx
var React = require('react');

var CommentBox = React.createClass({
  render: function() {
    return (
     <div className="commentBox">
        わけワカメ
      </div>
   );
  }
});

React.render(
  <CommentBox />,
  document.getElementById('content')
);
```

こちらの状態でビルドしてみたところ、下記のエラーが発生した。
```
 React.createClass is not a function
```

v0.14でビルドする場合に発生しているが、原因がわからなかった。。。

v0.13インストールし直しでビルドしてみる。
```
$ bower install react#0.13 -save-dev
$ gulp build
```

今回はエラーが発生せず、下記の画面が表示された。

![localhost 3000.png](https://qiita-image-store.s3.amazonaws.com/0/11290/45963132-9484-6364-2192-cda1371f619d.png)

>####追記
<a href="http://qiita.com/naru0504" target="_blank">naru0504<a/>さんよりコメント頂ました

>- React v0.14.xでビルドした際のバグはbower-webpack-pluginのバグの可能性有り
- webpackはnpmでのパッケージ管理を推奨している為、bowerではなく、なるべくnpmを使用したほうがいいかもしれない

##終わり
画面を表示するだけで大変でした。
もっとそれぞれの使い方について理解する必要があります。