WEB掻っ穿じり

WEB備忘録とチャリとカメラ

Gulp 4でバベる(babelifyとbrowserifyでimport/exportのモジュール間の依存関係を使いつつ、require文を使わないようにJavaScriptをBABELでトランスパイルしてまとめる)

  category:web

GulpのタスクにJavaScript構文をBABELでトランスパイル(ES5)ができるようにします。

加えてbabelifyとbrowserifyの処理を加えて、モジュール間の依存関係の解決(require文も吐き出さないようにしている)してJavaScriptを1ファイルにまとめるGulp処理を目指しました。

Gulp 4が既に使えることが前提です Gulp 4サクッと導入(nodenv版)

GulpでのBABELを導入

Gulpで必要なBABELモジュールをインストールする。

npm i -D @babel/core @babel/preset-env

インストール完了後のpackage.json(一部抜粋)

{
   "devDependencies": {
    "@babel/core": "^7.16.5",
    "@babel/preset-env": "^7.16.5"
  }
}

これだけで gulpfile.js にタスクを加えて対象のJavaScriptファイルをトランスパイルさせるようにはできるが、 JavaScriptのモジュールの依存関係 import/export 文を使ってトランスパイルすると吐き出される.jsファイルに require() 文が入ってしまい非対称ブラウザではエラーになってしまう。

browserifyを使ってファイルをまとめる必要があるのと、BABELでbrowserifyを使うためのプラグインもいくつか必要なことがわかった。

BrowserifyでJavaScriptを1ファイルにまとめる

browserifyとbabelify、それとvinyl-source-streamを新たにおインストールする。

npm i -D browserify babelify vinyl-source-stream

browserify

Browserify(ブラウザリファイ)はNode.js(サーバーサイドJavaScript)のモジュールシステムをブラウザでも利用できるようにしてくれるツール。

npmのモジュールをブラウザでも利用することが元来の目的であったのが、モジュール間の依存解決やファイル結合を行うための目的でビルドツールで使われるようになった経緯があるみたいです。

クライアントサイドJavaScriptのモジュール管理のデファクト・スタンダードみたいですね。

babelify

ES5にトランスパイルするBABELをBrowserifyで使えるようにするためのプラグイン

vinyl-source-stream

browserifyの .bundle() からチェーンで .pipe() させる時に必要になる(返り値のオブジェクトを vinylに変換してくれる)らしい


その他モジュールのインストール

npm i -D gulp-plumber gulp-uglify

gulp-plumber

gulpタスクのStream中のエラーでタスクが強制停止されるのを回避するモジュール。
コンパイルエラーなどでwatchタスクが止まってしまうのを防ぎます。

gulp-uglify

JavaScriptファイルを圧縮(Minify)させる

ここまでのインストール済みのモジュール、package.json(一部抜粋)

{
   "devDependencies": {
    "@babel/core": "^7.16.5",
    "@babel/preset-env": "^7.16.5",
    "babelify": "^10.0.0",
    "browserify": "^17.0.0",
    "gulp-plumber": "^1.2.1",
    "gulp-uglify": "^3.0.2",
    "vinyl-source-stream": "^2.0.0"
  }
}

gulpfile.jsにタスクを定義する

src/es6/*.js のJavaScriptファイルを、 dest/assets/js/main.js にまとめる処理。

(browserifyでsrc指定を使っておらず最後のminify処理がエラーになってしまうので、処理を分けてseriesで繋げている、、暫定処理)

const { src, dest, watch, series } = require('gulp')
const browser = require('browser-sync').create()
const plumber = require('gulp-plumber')
const uglify = require('gulp-uglify')
const browserify = require('browserify')
const babelify = require('babelify')
const source = require('vinyl-source-stream')

const transpileBabel = () => {
  return browserify('./src/es6/*.js',  { debug: false })
    .transform(babelify)
    .bundle()
    .pipe(plumber())
    .on("error", (err) => { console.log("Error : " + err.message) })
    .pipe(source('main.js'))
    .pipe(dest('./dist/assets/js/'));
}

const minify = (cb) => {
  src('./dist/assets/js/main.js')
    .pipe(uglify())
    .pipe(dest('./dist/assets/js/'));
  cb();
}

const watch = () => {
  watch('src/es6/*.js', series([transpileBabel, minify],reload));
}

const server = (cb) => {
  browser.init({
    server: { https: true },
    baseDir: './dist',
    server: "./dist",
    index: "index.html" 
  });
  watch()
  cb();
}

const reload = (cb) => {
  browser.reload();
  cb();
}

exports.default = server;

.babelrc ファイルの作成

rootディレクトリにBabelの設定ファイル .babelrc が必要なので、用意する。

touch .babelrc

.babelrcでプリセット指定

{
  "presets": [
    "@babel/preset-env"
  ]
}

これでgulpコマンドで対象のjsファイルがwatchされて、BABELトランスパイルの処理がはしるはず。

npx run gulp

まとめ

ライブラリやプラグインモジュールを多数importさせつつwatchで都度トランスパイルさせるとなると処理が停滞し、負荷も高くなってくるので、他プリプロセッサーのコンパイル処理などとは分けて、jsトランスパイルは監視させずに別途コマンドを作ってあげたほうがよさそう。

Webpackのようにjsバンドルにこだわらず、ちょっとした静的ページを作成するにはgulpの方が処理が早く適していると思う。