快適な開発環境を目指して(4)

fluxでの開発を見据えて、gulpを使った開発環境を作ってみた。
(Gulp + Browserify + ES6 + Babelify + Watchify + Brower-sync)

前提知識

  • gulp
  • ES6(ES2015)

材料

  • gulp...自動タスク管理ツール
  • Browsersync...ブラウザの自動リロード
  • browserify...依存物をバンドル
    • babelify...browserifyのプラグイン。ES6やReactの変換に使う
      • babel-preset-react...babelのreact用のプリセット
      • babel-preset-es2015...babelのes2015用のプリセット
    • watchify...同じくbrowserifyのプラグイン。gulpのwatchタスクとの似ているが、コードの差分を監視する。
  • vinyl-source-stream...与えたファイルの形式をgulpが扱うことのできるvinyl形式にしてくれる。

これらをインストールしておきます。

npm install --save-dev gulp browser-sync browserify babelify watchify vinyl-source-stream babel-preset-es2015 babel-preset-react

gulpfile.jsをES2015で書いていきます。まずはその準備として.babelrcファイルを作り、次のように編集しましょう。

{
  "presets": ["es2015","react"]
}

次にgulpfile.jsgulpfile.babel.jsにリネームします。これで準備はおk。このファイルにgulpタスクを記述していきます。

各レシピ

Browsersync

baseDirで対象のディレクトリ、indexでエントリーのファイルを指定する。

gulp.task('browserSync', () => {
  browserSync({
    server: {
      baseDir: './',
      index: 'index.html'
    }
  });
});

reloadを定義する。

gulp.task('reload', () => {
  browserSync.reload();
});

watchで監視し、ファイルに変更があればreloadタスクを実行。

gulp.watch('./index.html',  ['reload']);

browserify

compile関数の定義。babelifyのプリセットでReact、ES6をコンバート指定。 watchifyで監視するファイルを指定。

function compile(isWatch) {
  var bundler = watchify(browserify('./scripts/main.js', { debug: true }).transform(babelify, {presets: ["es2015", "react"]}));

  function rebundle() {
    bundler.bundle()
      .on('error', function(err) { console.error(err); this.emit('end'); })
      .pipe(source('build.js'))
      .pipe(gulp.dest('./build'));
  }

  if (isWatch) {
    bundler.on('update', function() {
      console.log('bundling js...');
      rebundle();
    });
  }

  rebundle();
}

watch関数でcompileを呼び出す。

function watch() {
  return compile(true);
};

gulpタスクの定義。

gulp.task('build', function() { return compile(); });
gulp.task('watch', function() { return watch(); });

できたもの

gulpfile.babel.js

import gulp from 'gulp';
import browserSync from 'browser-sync';
import browserify from 'browserify';
import babelify from 'babelify';
import watchify from 'watchify';
import source from 'vinyl-source-stream';

function compile(watch) {
  var bundler = watchify(browserify('./scripts/main.js', { debug: true }).transform(babelify, {presets: ["es2015", "react"]}));

  function rebundle() {
    bundler.bundle()
      .on('error', function(err) { console.error(err); this.emit('end'); })
      .pipe(source('build.js'))
      .pipe(gulp.dest('./build'));
  }

  if (watch) {
    bundler.on('update', function() {
      console.log('bundling js...');
      rebundle();
    });
  }

  rebundle();
}

function watch() {
  return compile(true);
};

gulp.task('build', function() { return compile(); });
gulp.task('watch', function() { return watch(); });

gulp.task('browserSync', () => {
  browserSync({
    server: {
      baseDir: './',
      index: 'index.html'
    }
  });
});

gulp.task('reload', () => {
  browserSync.reload();
});

gulp.task('default', ['browserSync','watch'], () => {
  gulp.watch('./index.html',  ['reload']);
  gulp.watch('./scripts/*.*', ['reload']);
  gulp.watch('./build/build.js', ['reload']);
  gulp.watch('./styles/*.*', ['reload']);
});

あとでwebpackも使ってみよう。