複数ファイルをbrowserifyするのにgulpを使うのを諦めた話


背景

browserifyは大変便利なコマンドです。
それ自体には、複数ファイルを処理するためのオプションはありません。

gulpgulp-browserifyを組み合わせて複数ファイルを処理する方法があります。

結論

gulp-browserifyは、既にメンテナンスされていません。
npm scriptでnpm-run-allを使って置き換えました。

npm scriptで置き換え

gulp-browserifyの場合

srcディレクトリにあるclient.jsexecute.jsを変換します。

gulpfile.js
const gulp = require('gulp')
const browserify = require('gulp-browserify')

const src = 'src/'
const dest = 'dest/'

gulp
  .task('browserify', () => gulp
    .src([
      `${src}client.js`,
      `${src}execute.js`
    ])
    .pipe(browserify())
    .pipe(gulp.dest(dest))
  )

npm scriptの場合

npm script内の複数コマンドをまとめて実行するのに、大変便利なnpm-run-allというモジュールがあります。
実行したいコマンドをnpm-run-all cmd1 cmd2という形で列挙することで、複数コマンドをまとめられます。

group-name:*という指定で、グループ指定することができるので、ここではそれを使います。
まとめて実行するコマンドは、browserifyコマンドそのものです。

package.json
  "scripts": {
    "browserify": "npm-run-all browserify:*",
    "browserify:client": "browserify -o dest/client.js src/client.js",
    "browserify:execute": "browserify -o dest/execute.js src/execute.js"
  }

置き換え手順

  1. npm i npm-run-all
  2. package.jsonにnpm scriptを追加
  3. 動作確認
  4. npm uninstall gulp gulp-browserify
  5. rm gulpfile.js

gulp-browserifyをやめた理由

READMEに大きく NOTE: THIS PLUGIN IS NO LONGER MAINTAINED と書かれています。
読みましょう(私は読まずに調査して、2時間使いました)。

gulp-browserifyはメンテナンスされていない

最後にpublishされたのがJan 7, 2015です。

gulp-browserifyが使っているbrowserifyが古い

使っているbrowserifyのバージョンは3.xです。
現在のbrowserifyの最新バージョンは13.0.1です。

ES6のパースに失敗することがある

requireした後で、アロー関数の引数でオブジェクトの分割代入をすると起きます。
具体的には

const {
  EventEmitter
} = require('events')
const em = new EventEmitter()

em.on('data', ({
    one,
    two
  }) => console.log(one + two))
em.emit('data', {one: 1, two: 2})

こういう感じです。
browserifyはJavaScriptのパーサーにAcronを使っています。
古いAcronのバグなのかな?と思っています。

issue をあげたところで、メンテされていない情報をもらいました。
これ以上は調べても、gulp-browserifyに取り込まれないので、調査をやめました。

もっと細かい背景

元々、ES6がブラウザに実装される以前の時代(2014年10月)に実装していました。
ES6をES5に変換するために、browserifyと同時にbabelifyを使っていました。
現在のバージョンのブラウザで、使用しているES6文法がそのまま動くのが確認でき、直前にbabelifyを外しました。
babelifyを使っていればbrowserifyの実行前に、ES5への変換されます。
ES6のパースエラーは起きなかったのではないかと思います(試していません)。