gulp を用いたフロントエンドのタスク自動化レシピ (1)

browserify でのトランスパイルや uglify といったフロントエンド用のタスクを gulp で自動化するレシピを Github に上げ始めました.

github.com

browserify でトランスパイルを行い,1つのファイルにまとめるタスクを書いたので,簡単な解説を残します.

browserify-single-bundle

このレシピでは,ES2015 で書かれた JS ファイルをトランスパイルし,1つにまとめるタスクを gulp で書いています. また,ファイル監視による自動トランスパイル,ソースマップ付きファイル圧縮を行うかをオプションで指定できるようになっています.

本レシピで使用している主なモジュールは以下の通りです.

  • browserify
    • babelify
    • watchify
    • licensify
  • gulp-sourcemaps
  • gulp-uglify
  • gulp-util

追記(7/24)

licensifyを追加しました.

bundleJS(isWatch, isUglify)の解説

このレシピの要はbundleJS(isWatch, isUglify)で,引数をtrue, falseで変えることでファイル監視,ファイル圧縮を切り替えます.

isWatchtrueの場合,browserify に watchify がプラグインとして指定され,ファイル監視が有効になります.
isUglifytrueの場合,bundle()で gulp-sourcemaps, gulp-uglify でのインラインソースマップの生成とファイル圧縮が有効になります.

browserify は,debug: trueを指定するとインラインソースマップを生成します. gulp-sourcemaps は,browserify が生成したインラインソースマップを読み込み,ファイル圧縮後のソースマップと対応づけてくれます. 通常,ファイル圧縮後のdest/js/common.jsのソースマップは browserify でトランスパイル後のファイルと対応づけがされてしまい,トランスパイル前のファイルへとジャンプできませんが,gulp-sourcemaps を利用することで,ファイル圧縮後のdest/js/common.jsからsrc/js/app.jsへジャンプ可能となります.

bundle()pipe()処理中に,isUglifyで処理を切り替えています. isUglify === falseの場合,pipe($.sourcemaps.init({loadMaps: true})), pipe($.uglify())の代わりにpipe($.util.noop())が実行されます. $.util.noop()は gulp-util のnoop()であり,何もしない Stream を生成します.
noop()を用いると,このように特定の条件のときのみpipe()で処理を行うといった記述が可能になるため,状況によっては便利だと思います.

const bundleJS = (isWatch, isUglify) => {
  const src = 'src/js/app.js';
  const bundler = browserify(src, {
    debug: true,
    cache: {},
    packageCache: {},
  });

  bundler.transform(babelify);
  bundler.plugin(licensify);

  const bundle = () => {
    return bundler.bundle()
      .on('error', (err) => {
        $.util.log('browserify error', err);
      })
      .pipe(source('common.js'))
      .pipe(buffer())
      .pipe(isUglify ? $.sourcemaps.init({loadMaps: true}) : $.util.noop())
      .pipe(isUglify ? $.uglify({ preserveComments: 'license' }) : $.util.noop())
      .pipe(isUglify ? $.sourcemaps.write() : $.util.noop())
      .pipe(gulp.dest('dest/js'));
  };

  if (isWatch) {
    bundler.plugin(watchify);
    bundler.on('update', bundle);
  }

  bundler.on('log', $.util.log);

  return bundle();
};