gulp + webpack + reactの最小構成


（※この記事は古いのでこちらをご覧ください。http://qiita.com/uryyyyyyy/items/63969d6ed9341affdffb ）

## 問題提起

Reactを始めたい、色々試してみたいけど

- サンプルコードにrequire()がついてて、webpackとか必要じゃん。。。
- jsxのコンパイルを自動化しようと思ったらgulpか。。。

とか、導入にあたってのハードルが高い。gulpとかwebpackとかよくわかんない。

ということで仕組みを理解するために最小構成を用意してみました。

間違っている点があればご指摘いただけると嬉しいです。

## 参考資料

http://yutapon.hatenablog.com/entry/2014/12/06/123000

他色々

## 構成

今回の構成は以下です。

```
$ tree .
.
├── gulpfile.js
├── package.json
├── source
│   ├── Hello.jsx
│   ├── index.html
│   └── main.jsx
└── webpack.config.js
```

### package.json

```json:package.json
{
  "name": "webpack_sample",
  "description": "",
  "version": "1.0.0",
  "author": "uryyyyyyy",
  "dependencies": {
    "react": "^0.12.2"
  },
  "devDependencies": {
    "gulp": "^3.8.10",
    "gulp-webpack": "^1.1.2",
    "jsx-loader": "^0.12.2",
    "rimraf": "^2.2.8"
  }
}
```

- gulp
  - gulpfileの中で使います。CommandLineで使うにはglobal installします。
- gulp-webpack
  - gulpタスクの中でwebpackを使います。
- jsx-loader
  - webpackの中でjsxをjsにコンパイルしてくれます。
- rimraf
  - 指定したディレクトリをcleanしてくれます。

### webpack.config.js

```js:webpack.config.js
module.exports = {
    entry: './source/main.jsx',
    output: {
      filename: './build/bundle.js'
    },
    devtool: 'inline-source-map',
    module: {
      loaders: [
    { test: /\.jsx$/, loader: 'jsx-loader' }
      ]
    },
    resolve: {
      extensions: ['', '.js', '.jsx']
    }
};
```

webpackの設定ファイルです。
デフォルトで`webpack.config.js`という名前のファイルを読みに行くようです。

ちなみに、`npm install webpack -g`した状態でこの階層で`webpack`と打っても上手いことやってくれます。

- entry
  - entrypointです。このファイルのrequireをどんどん辿っていきます。
- output.filename
  - 全てまとめたファイルがここに出力されます。
- devtool
  - http://webpack.github.io/docs/configuration.html#devtool
  - debug用のツールが使えます。
  - 今回は実行時にsoucemapを表示してくれるものを入れてみます。
- module.loaders
  - http://webpack.github.io/docs/configuration.html#module-loaders
  - ファイルがある条件を満たしてたらloaderで変換されます。
  - 今回は*.jsxをjsxコンパイラに通すようにします。
-  resolve.extensions
  - http://webpack.github.io/docs/configuration.html#resolve-extensions
  - 対象ファイルをModuleと認識します。
  - 今回は３つを含めます。なぜか、どれか一つでも欠けるとエラーになります。。。


### gulpfile.js

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

gulp.task('cleanBuild', function (cb) {
  var rimraf = require('rimraf');
  rimraf('./build/', cb);
});

gulp.task('copyIndex', ['cleanBuild'], function () {
  return gulp.src('./source/index.html')
  .pipe(gulp.dest('./build/'));
});

gulp.task('build', ['copyIndex'], function (cb) {
  return gulp.src('')
  .pipe(webpack(webpackConfig))
  .pipe(gulp.dest(''));
});
```

とりあえず`gulp build`と叩けば動作するようにした。

仕組みとしては、

buildタスクの前に、copyIndexタスクの前に、cleanBuildタスクが呼ばれる。

- cleanBuildタスク
  - buildディレクトリをcleanする。
- copyIndexタスク
  - index.htmlをコピーする。
- buildタスク
  - webpackを実行する。設定は`webpack.config.js`から読み込む。

### source

```html:index.html
<!DOCTYPE html>
<html>
<body>
  <div id="example"></div>
</body>
<script src="./bundle.js"></script>
</html>
```

scriptの読み込みを最後にしないと、Reactが`Target container is not a DOM element.`みたいなエラーを出して焦るので注意。

参照するjsファイルは、webpackでまとめられた後のファイルにしておく。


```js:main.jsx
/** @jsx React.DOM */
var Hello = require('./Hello');
var React = require('react');

React.render(
  <Hello />,
  document.getElementById('example')
);
```

今回のエントリーポイント。
exampleにHelloをマウントするだけ。


```js:Hello.jsx
/** @jsx React.DOM */
var React = require('react');
var Hello = React.createClass({
  getInitialState: function () {
    return { name: "not clicked"  };
  },
  onClick: function () {
    this.setState( {name: "clicked" });
  },
  render: function() {
    return <div onClick={ this.onClick } >{this.state.name}</div>;
  }
});

module.exports = Hello;
```

`require('Hello')`で呼ばれるやつ。中身は何でも良いけど単純なイベントを含むものにしてみた。

## Buildしてみる

事前準備として

- `npm install gulp -g`されてること。
- `npm install`と打って依存ライブラリをインストールしておくこと。

準備が済んだら、`gulp build`と打つ。

```
$ gulp build
[22:12:01] Using gulpfile /hoge/gulpfile.js
[22:12:01] Starting 'cleanBuild'...
[22:12:01] Finished 'cleanBuild' after 3.1 ms
[22:12:01] Starting 'copyIndex'...
[22:12:01] Finished 'copyIndex' after 17 ms
[22:12:01] Starting 'build'...
[22:12:03] Version: webpack 1.4.15
            Asset     Size  Chunks             Chunk Names
./build/bundle.js  1530407       0  [emitted]  main
[22:12:03] Finished 'build' after 1.93 s

```

こんな感じになれば成功。`build/index.html`を見てみると、ちゃんと動いてる。

developers toolのsourceを見ると、webpackってとこでsourceMapが表示されてる。

## まとめ

ReactはcommonJSスタイルで進化を発揮するっぽい（Jestで単体テストできる。モジュール化できる。）。
ただ、準備がちょっとめんどい。

とりあえずこんな感じでReact試してみようよ。