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の方が処理が早く適していると思う。