Gulp(React.js+Browserify)でyak shaving

人間の欲は深いのでyak shavingが生じます。その例です。

yak shavingしてるので最終形態をはじめにのせておきます、目次だけ見てこちらを参考にするのもいいかもしれません。

[Gulp, browserify, reactify, coffee-reactify, notify and watchify for coffeescript](https://gist.github.com/yymm/49c44016ac0087944490 "Gulp, browserify, reactify, coffee-reactify, notify and watchify for coffeescript")

ディレクトリ構成

```
package.json
build/
  - app.js
src/
  - app.coffee
  - foo.coffe
  - bar.coffe 
```

# Browserify + React.js

シンプルな例です。

```bash
$ npm install react browserify reactify vinyl-source-stream -save
```

```gulpfile.coffee
ulp = require('gulp')

browserify = require('browserify')
source = require('vinyl-source-stream')

gulp.task 'default', ->
    return browserify
            entries: './src/app.js'
            transform: ['reactify']
        .bundle()
        .pipe source('bundle.js')
        .pipe gulp.dest('./build')
```

Ref:

* [Gulp + Browserify: The Everything Post | Viget](http://viget.com/extend/gulp-browserify-starter-faq "Gulp + Browserify: The Everything Post | Viget")

# CoffeeScriptで書きたいです

Javascriptではなく、CoffeeScriptが使いたいです。

```bash
$ npm install coffee-reactify coffee-script
```
```gulpfile.coffee
gulp = require('gulp')

browserify = require('browserify')
source = require('vinyl-source-stream')

gulp.task 'default', ->
    return browserify
            entries: './src/app.coffee'
            transform: ['coffee-reactify']
        .bundle()
        .pipe source('bundle.js')
        .pipe gulp.dest('./build')
```
Ref:

* [reactjs - Browserify: Can't seem to get reactify to work with coffeeify - Stack Overflow](http://stackoverflow.com/questions/24278602/browserify-cant-seem-to-get-reactify-to-work-with-coffeeify "reactjs - Browserify: Can't seem to get reactify to work with coffeeify - Stack Overflow")
* [jsdf/coffee-reactify](https://github.com/jsdf/coffee-reactify "jsdf/coffee-reactify")
* [gulpでbrowserify使ってcoffee-scriptの監視とコンパイル - Qiita](http://qiita.com/mizchi/items/10a8e2b3e6c2c3235e61 "gulpでbrowserify使ってcoffee-scriptの監視とコンパイル - Qiita")

# 複数ファイルをBrowserifyしたいです

```bash
$ npm install glob -g
```

```gulpfile.coffee
gulp = require('gulp')
glob = require('glob')

browserify = require('browserify')
source = require('vinyl-source-stream')

gulp.task 'default', ->                                                                                                                                                                       
    srcFiles = glob.sync('./src/*.coffee')
    return browserify
            entries: srcFiles
            transform: ['coffee-reactify']
        .bundle()
        .pipe source('bundle.js')
        .pipe gulp.dest('./build')
```

Ref:

* [automated tests - Browserify - multiple entry points - Stack Overflow](http://stackoverflow.com/questions/24087791/browserify-multiple-entry-points "automated tests - Browserify - multiple entry points - Stack Overflow")

# Watchしたいです

gulp-watchを使う方法です。

```bash
$ npm install gulp-watch -save
```

```gulpfile.coffee
gulp = require('gulp')
glob = require('glob')
watch = require('gulp-watch')

browserify = require('browserify')
source = require('vinyl-source-stream')

gulp.task 'default', ->
    srcFiles = glob.sync('./src/*.coffee')
    return browserify
            entries: srcFiles
            transform: ['coffee-reactify']
        .bundle()
        .pipe source('bundle.js')
        .pipe gulp.dest('./build')

gulp.task 'watch', ->
    gulp.watch './src/*.coffee', ['default']
```

この場合だと、ビルドに失敗した場合、watchしてるnodeのプロセスが落ちてしまいます。以下の記事を参考にして修正するといいかもしれません。

この問題は、以下の"Notifyしたいです"でも解決しているので、好きな方を試してみてください。

[browserifyでgulp-plumberが効かない時の対処方法 - Qiita](http://qiita.com/tanshio/items/b546b4b3eb2c648cb340 "browserifyでgulp-plumberが効かない時の対処方法 - Qiita")

# Notifyしたいです

gulp-watchを使ってもできますが、watchifyを使ってやります。今までのgulpfileはぶち壊します。

```bash
$ npm install gulp-notify gulp-util watchify
```

```coffeescript:gulpfile.coffee
source = require 'vinyl-source-stream'
gulp = require 'gulp'
gutil = require 'gulp-util'
browserify = require 'browserify'
coffee_reactify = require 'coffee-reactify'
watchify = require 'watchify'
notify = require 'gulp-notify'
glob = require 'glob'
 
paths =
    srcFiles: glob.sync('./src/*.coffee')
    build: './build/'
    buildFile: 'bundle.js'
 
 
buildScript = (files, watch) ->
    rebundle = ->
        stream = bundler.bundle()
        stream.on("error", notify.onError(
            title: "Compile Error"
            message: "<%= error.message %>"
        )).pipe(source(paths.buildFile)).pipe gulp.dest(paths.build)
 
    props = watchify.args
    props.entries = files
    props.debug = true
 
    bundler = (if watch then watchify(browserify(props)) else browserify(props))
    bundler.transform coffee_reactify
    bundler.on "update", ->
        rebundle()
        gutil.log "Rebundled..."
        gutil.log paths.srcFiles
        return
 
    rebundle()
 
 
gulp.task "default", ->
    buildScript paths.srcFiles, false
 
gulp.task "watch", ["default"], ->
    buildScript paths.srcFiles, true
```

Error時

![スクリーンショット 2015-03-12 16.01.48.png](https://qiita-image-store.s3.amazonaws.com/0/24784/e05781d7-736c-0419-1092-2be48eff283b.png)


benrify!

Ref:

* [Gulp, browserify, reactify, notify and watchify for coffeescript](https://gist.github.com/vojd/a2d277bc161a2674aeaa "Gulp, browserify, reactify, notify and watchify for coffeescript")
* [How to keep a fast build with Browserify and ReactJS | Avisi Blog](http://blog.avisi.nl/2014/04/25/how-to-keep-a-fast-build-with-browserify-and-reactjs/ "How to keep a fast build with Browserify and ReactJS | Avisi Blog")
* [gulpfile.js with browserify, reactify, watchify and gulp-notify.](https://gist.github.com/Sigmus/9253068 "gulpfile.js with browserify, reactify, watchify and gulp-notify.")

# まとめ

このように、React.jsを使ってなにか作りたいのに、gulpの設定で一日の大半が終わってしまいます。

まだ、concatとかほしいですね。

いい加減にしましょう。