gulp3のrun-sequence + エラー処理なコードを、gulp4で置き換える
いろいろ
gulp3にタスクを連続で実行するrun-sequenceというライブラリがありました。
gulpのバージョン4以降では、このrun-sequenceの代わりに、gulp.seriesを使うことになったのだが、
gulp.seriesには、run-sequenceにあった、発生したエラーを受け取るcallbackが用意されていませんでした。
try-catch文を使っても、gulp.series内で発生したエラーを拾うことはできない。
では、gulp3 → gulp4と書き換える際、run-sequenceをどのように書き換えるべきか。
- run-sequence
gulp3 + run-sequenceのコード
run-sequenceでは、こんな感じで発生したエラーを拾えていた。
const gulp = require('gulp'); const runSequence = require('run-sequence'); gulp.task('package', (cb) => { runSequence('tsc-debug', '_rm-package', '_package-debug', (err) => { if (err) { gulp.start('_notifyError'); } cb(err); }); });
gulp4 + gulp.seriesのコード
エラーを拾うコールバックがgulp.seriesに用意されていないので、
すんなりgulp4に書き換えられない。
エラー処理が抜けてしまう。
const gulp = require('gulp'); gulp.task('package', gulp.series('tsc-debug', '_rm-package', '_package-debug'));
gulp.seriesのコードを追ってみる
gulpの各タスクの処理はtaskWrapperで包まれる。
// node_modules/undertaker/lib/set-task.js function taskWrapper() { return fn.apply(this, arguments); }
gulp.seriesを作成時、createExtensionsが呼ばれる。
// node_modules/undertaker/lib/series.js function series() { var create = this._settle ? bach.settleSeries : bach.series; var args = normalizeArgs(this._registry, arguments); var extensions = createExtensions(this); // ←←←←←←←←←←←←←←←←←←← var fn = create(args, extensions);
createExtensionsで、エラー処理のハンドリングが実装されている
- エラー発生時にerrorイベントが発行される
// node_modules/undertaker/lib/helpers/createExtensions.js function createExtensions(ee) { return { error: function(error, storage) { if (Array.isArray(error)) { error = error[0]; } storage.release(); ee.emit('error', { // ←←←←←←←←←←←←←←←←←←← uid: storage.uid, name: storage.name, branch: storage.branch, error: error, duration: process.hrtime(storage.startHr), time: Date.now(), }); },
最終的にgulpでエラーを拾える
- つまり、gulp.series内で発生したエラーは、次のようなコードで拾える。
- gulp.on('error', エラー処理)
const gulp = require('gulp'); gulp.on('error', (err) => { // ←←←←←←←←←←←←←←←←←←← console.log('--- catch error'); });
gulp.seriesで発生したエラーを拾うコードの例(全体)
const gulp = require('gulp'); gulp.task('hello', (cb) => { console.log('hello'); return cb(); }); gulp.task('world', (cb) => { console.log('world'); return cb(); }); gulp.task('gulp', (cb) => { console.log('gulp'); throw new Error('error from task "gulp"'); }); gulp.on('error', (err) => { console.log('--- catch error'); }); gulp.task('run', gulp.series('hello', 'world', 'gulp'));
npmのモジュールにしてみた
- gulp3 run-sequenceの処理を、なるべくそのままgulp4.seriesに置き換えれるようにするnpmモジュール
- https://www.npmjs.com/package/gulp-task-err-handler
- ちゃんとgulp4に合わせて書き換えろ?うん、そういう意見もあると思う。
npm install --save-dev gulp-task-error-handler
gulp3 run-sequenceのコードを、gulp4 gulp.seriesで置き換える例
- gulp3 run-sequence code
- 例えば、このようなコードがあったとして、
const gulp = require('gulp'); const runSequence = require('run-sequence'); gulp.task('package', (cb) => { runSequence('tsc-debug', '_rm-package', '_package-debug', (err) => { if (err) { gulp.start('_notifyError'); } cb(err); }); });
- replace with gulp-task-error-handler sample.
- このモジュールを使うと、このように置き換えられる。
const gulp = require('gulp'); const handleError = require('gulp-task-error-handler'); gulp.task('package', handleError(gulp.series('tsc-debug', '_rm-package', '_package-debug'), (err) => { gulp.task('_notifyError')(); }) );
おわり
おわりなのだ。