Gulp.watch:エラーを正しくキャッチする

最新のすべてのフロントエンドビルドシステムには、 watch



モードがあります。 watch



モードでは、ファイルが保存された直後にファイルを自動的に再構築する特別なデーモンが起動されます。 gulp.jsもありますが、機能が少し複雑になっています。 gulp.jsの作業は、ファイルをストリームとして処理することに基づいています。 また、スレッド内のエラーを常にキャッチできるわけではなく、エラーが発生すると、キャッチされない例外がスローされ、プロセスが終了します。



これを防ぐために、ウォッチャーは個々のエラーを無視してファイルを保存するときに何度も実行することができます。gulpでは、この記事で説明する追加設定を行う必要があります。



何が起こっているの?



まず、何が起こるのか、なぜウォッチャーがクラッシュするのかを見てみましょう。 gulpプラグインを作成する場合、プラグインの実行中にエラーが発生したときにerror



イベントをスローすることをお勧めします。 ただし、ビルドシステムの基になっているnodejsスレッドでは、エラーが気付かれることはありません。 error



イベントにサブスクライブしているユーザーがいない場合、例外がスローされ、メッセージがユーザーに正確に届きます。 その結果、gulpを使用する場合、開発者はこのようなエラーをよく目にします。



 events.js:72 throw er; // Unhandled 'error' event
      
      







Continious-Integration(CI)を使用する場合、コミットごとに自動チェックが起動されると、これが役立つ場合があります(アセンブリが失敗し、ビルドがアセンブルされなかったため、責任者は通知を受け取ります)。 しかし、絶えず再起動する必要のある、ローカル開発の絶え間ない監視者は大きな迷惑です。



どうする



インターネットでは、 stackoverflowトースターの両方このトピックに関する質問を見つけることができます。 質問への回答は、いくつかの一般的なソリューションを提供します。



error



イベントをサブスクライブできます。



 gulp.task('less', function() { return gulp.src('less/*.less') .pipe(less().on('error', gutil.log)) .pipe(gulp.dest('app/css')); });
      
      







gulp-plumberプラグインを接続できます。これは、1つのプラグインのerror



をサブスクライブするだけでなく、パイプを介して接続された後続のすべてのプラグインに対して自動的にこれを行います。



 gulp.task('less', function() { return gulp.src('less/*.less') .pipe(plumber()) .pipe(less()) .pipe(gulp.dest('app/css')); });
      
      







なぜこれをしないのですか



問題は解決されたようですが、そうではありません。 アセンブリエラーがキャッチされ、コンソールでメッセージが表示され、実行中のデーモンウォッチャーはクラッシュしませんが、新しい問題が発生しました。



計算用のスクリプトが作成されているCIサーバーがあるとします。 アセンブリを時計と連動させるために、上記の解決策のいずれかを適用しました。 しかし今では、ビルドエラーが発生しても、ビルドはまだ成功としてマークされていることがわかります。 gulpコマンドは常にコード0で終了します。CIアセンブリの場合、エラーを飲み込む必要はありません。 ウォッチモード専用のエラーハンドラを追加できますが、これによりアセンブリの説明が複雑になり、ミスをする可能性が高くなります。 幸いなことに、同じ方法でアセンブリを構成する方法がありますが、同時にビルドモードと監視モードの両方で作業をサポートします。



解決策



実際、gulpはファイルストリームのエラーをリッスンしようとしています。 しかし、通常、最後の呼び出しは結果をディスクに書き込むgulp.dest()



であり、中間プラグインでエラーが発生するため、エラーはチェーンの最後に到達しないため、gulpはそれを認識しません。 たとえば、次のチェーンを考えてみましょう。



 stream1.on('error', function() { console.log('error 1') }) stream2.on('error', function() { console.log('error 2') }) stream3.on('error', function() { console.log('error 3') }) stream1 .pipe(stream2) .pipe(stream3); stream1.emit('error'); //     "error 1"
      
      







たとえば、promiseとは異なり、スレッド内のエラーはチェーンに沿ってさらに伝播することはなく、各スレッドで個別にインターセプトする必要があります。 この理由でio.jsにpull-requestがありますが、現在のバージョンではチェーンの最後にエラーを渡すことはできません。 したがって、gulpは中間スレッドからエラーをキャッチすることはできず、独自にこれを行う必要があります。



ただし、タスクの説明としてのgulpは、ストリームを返す関数だけでなく、node.jsの多くのAPIのような通常のコールバックスタイルの関数も受け入れます。 そのような関数では、タスクがエラーで完了したときと成功したときを自分で決定します。



 gulp.task('less', function(done) { gulp.src('less/*.less') .pipe(less().on('error', function(error) { //    done(error); })) .pipe(gulp.dest('app/css')) .on('end', function() { //      done(); }); });
      
      







gulpの作業の一部を現在行っているため、このようなアセンブリの説明はもう少し見えますが、現在は正しく処理しています。 そして、 このような補助関数を自分で書くと、その違いはほとんど認識できなくなります。



 gulp.task('less', wrapPipe(function(success, error) { return gulp.src('less/*.less') .pipe(less().on('error', error)) .pipe(gulp.dest('app/css')); }));
      
      







ただし、保存中の開発中と再構築中、およびビルド中のCIサーバーの両方で、コンソールに正しいメッセージが表示されます。



All Articles