gulp-parcelを使って複数のJSファイルを1つにバンドルする

自分用のWeb作成ボイラープレートである「Ususama」はgulpを使っているのですが、JSファイルを機能ごとに分離したくなってきました。 そこでモジュールバンドラを考えたのですが、既にScssやejsのコンパイル、画像の圧縮などの機能は盛り込んであるので、Webpackは機能多過と感じました。 今更Browserifyというのもちょっと(そもそもgulpの時点で、というのはありますが)、と思い、すわRollupかとも思ったのですが、Babelと合わせる際のプラグインでわりとごちゃごちゃしそう……と感じていたところに、そういえばParcelはどうだろうか、と思い立ちました。 少し検索してみると、ファイル出力先が調整できるようになっていたり、だいぶ使えそうな感じになっていたので、設定ファイルの煩わしさもなくなれば……と期待を込めて取り掛かってみました。 gulpがベースにあるので、gulp用のプラグインはないかとnpmを探してみたところ、gulp-parcelというものが見付かりました。 個人開発なので今後がどうなるか分かりませんが、とりあえずこれで試してみることにします。 試すのは以下のJSファイル。

app.js

import pageTop from './_pageTop'

$(() => {
//略
    //スクロール対象を取得
    const screlm = scrollElm()
    pageTop(screlm)
//略
}
//略

_pageTop.js

export default (screlm) => {
//略
}
どちらもsrc/js/ディレクトリに置いてあるものとし、gulp-parcelによる中間出力はsrc/js/parcel/以下に行うものとします。 なので、上記の変更に対応するJSをトランスパイルする順番と条件を以下のようにします(もっとバリバリモジュールバンドラでまとめても良いのですが、ひとまずできるかどうかの実験のため最小限の変更とします)。
  1. jQueryなどのライブラリをまとめてsrc/js/concat/lib.jsに出力(js.concatというタスク名)
  2. 今回の本題。Parcelでsrc/js/以下のJSファイルをエントリポイントにしてバンドルする
    • ただし、以下のファイルは除く
      • 先頭が_で始まるjsファイル(Scssと同じルールとする)
      • src/js/concat/以下のファイル(既にバンドルされているので)
      • src/js/parcel/以下のファイル(無限ループになってしまうので)
  3. 1.,2.が完了したら、今までと同様にgulp-uglify-esでminifyする
以上を満たすようにしたJSのタスクが以下。
_.gulp.task('js.concat', () => {
//略。今まで通り
})
_.gulp.task('js.parcel', () => {
    return _.gulp.src([`${dir.src.js}/**/*.js`, `!${dir.src.js}/**/_*.js`, `!${dir.src.js}/concat/**/*.js`, `!${dir.src.js}/parcel/**/*.js`], { read:false }) //2.の条件を満たすようにsrcを列挙。read:falseは付けないと動かないとのこと
        .pipe(_.plumber())
        .pipe(_.parcel({ //parcelのオプション
            cache: false,
            minify: false,
            hmr: false
        }))
        .pipe(_.gulp.dest(`${dir.src.js}/parcel/`)) //parcelディレクトリ下に出力
})
_.gulp.task('js.uglify', _.gulp.series(_.gulp.parallel('js.concat', 'js.parcel'), () => { //1.2.3.の順番を満たすようにgulp.seriesとgulp.parallelを使用
    return _.gulp.src([`${dir.src.js}/parcel/**/*.js`, `${dir.src.js}/concat/**/*.js`]) //uglifyしたいファイルはparcelとconcatの下にしかないのでsrcを調整
        .pipe(_.plumber()) //後は今まで通り
        .pipe(_.uglify({output: {comments: 'some'}}))
        .pipe(_.rename((path) => {
            path.dirname = dir.dist.js
            path.basename += '.min'
            path.extname = '.js'
        }))
        .pipe(_.gulp.dest('./'))
}))
こんな感じになりました。複数ファイルの際に動くかどうかまでは未検証ですが、とりあえずgulpとparcelを組み合わせてバンドルされ、ブラウザで今までと同じ動作になったことを確認しました。

参考

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。