ReactをGulpでbabelifyしてUnexpected tokenでこけたら

React書いてGulpでビルドしようとしたら``Unexpected token``エラーが出るのでググると **babel-preset-react** 入れないとダメだった。

こけた後に出来るだけ最小構成にしてReactの書き方がまずかったかgulpfile.jsの書き方がまずかったのか確認した内容の備忘録。

## エラー内容
```
% gulp
[03:57:42] Using gulpfile ~/react-gulp/gulpfile.js
[03:57:42] Starting 'default'...
events.js:142
      throw er; // Unhandled 'error' event
      ^

SyntaxError: ~/react-gulp/src/app.js: Unexpected token (6:2)
  4 |
  5 | ReactDOM.render(
> 6 |   <Child />,
    |   ^
  7 |   document.getElementById('container')
  8 | );
  9 |
    at Parser.pp.raise (~/react-gulp/node_modules/babylon/lib/parser/location.js:22:13)
    at Parser.pp.unexpected (~/react-gulp/node_modules/babylon/lib/parser/util.js:91:8)
    at Parser.pp.parseExprAtom (~/react-gulp/node_modules/babylon/lib/parser/expression.js:510:12)
    at Parser.pp.parseExprSubscripts (~/react-gulp/node_modules/babylon/lib/parser/expression.js:265:19)
    at Parser.pp.parseMaybeUnary (~/react-gulp/node_modules/babylon/lib/parser/expression.js:245:19)
    at Parser.pp.parseExprOps (~/react-gulp/node_modules/babylon/lib/parser/expression.js:176:19)
    at Parser.pp.parseMaybeConditional (~/react-gulp/node_modules/babylon/lib/parser/expression.js:158:19)
    at Parser.pp.parseMaybeAssign (~/react-gulp/node_modules/babylon/lib/parser/expression.js:121:19)
    at Parser.pp.parseExprListItem (~/react-gulp/node_modules/babylon/lib/parser/expression.js:988:16)
    at Parser.pp.parseCallExpressionArguments (~/react-gulp/node_modules/babylon/lib/parser/expression.js:341:20)
```

## プロジェクト構成
```
.
├── gulpfile.js
├── index.html
├── node_modules
├── package.json
└── src
    ├── app.js
    └── child.react.js
```

### node_modules
入れたものリスト

```
"devDependencies": {
  "babelify": "^7.2.0",
  "browserify": "^12.0.1",
  "gulp": "^3.9.0",
  "vinyl-source-stream": "^1.1.0"
},
"dependencies": {
  "react": "^0.14.3",
  "react-dom": "^0.14.3"
}
```

### gulpfile.js
```
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');

gulp.task('default', function () {
  return browserify('./src/app.js')
    .transform(babelify)
    .bundle()
    .pipe(source('bundle.js'))
    .pipe(gulp.dest('./'));
});
```

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

### src/app.js
```
var React = require('react');
var ReactDOM = require('react-dom');
var Child = require('./child.react.js');

ReactDOM.render(
  <Child />,
  document.getElementById('container')
);
```

### src/child.react.js
```
var React = require('react');

var Child = React.createClass({
  render: function () {
    return (
      <div id="child">
        <h2>Child</h2>
      </div>
    );
  }
});

module.exports = Child;
```

## 解決策
これで ``gulp`` を実行すると冒頭のエラーが出るので冒頭に書いているように　**babel-preset-react** をインストール(``npm install --save-dev babel-preset-react``)してgulpfile.jsを修正すればビルド成功する。

### インストール後のdevDependencies(package.js)
```
"devDependencies": {
  "babel-preset-react": "^6.3.13",
  "babelify": "^7.2.0",
  "browserify": "^12.0.1",
  "gulp": "^3.9.0",
  "vinyl-source-stream": "^1.1.0"
}
```

### 修正後のgulpfile.js
```
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');

gulp.task('default', function () {
  return browserify('./src/app.js')
    .transform(babelify,{presets: ["react"]})
    .bundle()
    .pipe(source('bundle.js'))
    .pipe(gulp.dest('./'));
});
```

### ビルド結果
これで``gulp``を実行するとちゃんと``bundle.js``ができあがってブラウザで``<h2>Child</h2>``のレンダリング結果が表示される。

```
% gulp
[04:11:17] Using gulpfile ~/react-gulp/gulpfile.js
[04:11:17] Starting 'default'...
[04:11:20] Finished 'default' after 3.67 s
```

### ビルド後の構成
```
.
├── bundle.js
├── gulpfile.js
├── index.html
├── node_modules
├── package.json
└── src
    ├── app.js
    └── child.react.js
```

## 参考
- [https://babeljs.io/blog/2015/10/29/6.0.0/](https://babeljs.io/blog/2015/10/29/6.0.0/)
- [https://github.com/babel/babelify#options](https://github.com/babel/babelify#options)