Gulp 目前的錯誤處理方式有點操蛋,一旦發生錯誤進程就掛了,得手動去重啟。雖然開發者預期在 gulp 4 中解決此問題 ,但 gulp 4 什么時候發布並沒有明確時間表,在此之前,還是很有必要了解一下更優雅的錯誤處理方式,除非你鍾情於反復在命令行里輸入 gulp 然后回車。
使用 Stream 事件 API 處理錯誤
Stream 發生錯誤時,會觸發 error 事件,監聽 error 事件進行錯誤處理可以避免 gulp 進程崩潰。
基本錯誤處理
下面的例子中,添加了 Less 編譯的錯誤處理,Less 發生編譯錯誤時,會在命令行輸出錯誤信息,gulp 進程不會掛掉,修正錯誤后,watch 任務將繼續執行。
注意:使用 gulp-util 只是使錯誤日志格式與 gulp 的日志保持一致,如果不想多一個依賴,可以直接使用 console 。
var gulp = require('gulp');
var less = require('gulp-less');
var csso = require('gulp-csso');
var gutil = require('gulp-util');
gulp.task('less', function() {
return gulp.src('less/app.less')
.pipe(less())
.on('error', function(err) {
gutil.log('Less Error!', err.message);
this.end();
})
.pipe(csso())
.pipe(gulp.dest('./dist'))
});
gulp.task('watch', function() {
gulp.watch('less/**/*.less', ['less']);
});
gulp.watch 與 Browserify 中的錯誤處理
Browserify 中的常規流與 gulp 中的 vinyl 對象流有點不同,browserify 的錯誤處理中需要手動觸發 end 事件 ,以停止流在管道中傳送。如果不添加 this.emit('end'); ,進程仍然會掛掉。
var gulp = require('gulp');
var browserify = require('browserify');
var source = require("vinyl-source-stream");
gulp.task('browserify', function(){
return browserify('./main.js').bundle()
.on('error', function(err){
console.log(err.message);
this.emit('end');
})
.pipe(source('main.out.js'))
.pipe(gulp.dest('./dist'));
});
使用插件
使用 Stream 的事件 API 雖然可以處理錯誤,但是在每個插件后面都需要添加錯誤監聽函數,有點惡心,還好有專門的插件處理這個問題。
gulp-plumber
gulp-plumber 可以阻止 gulp 插件發生錯誤導致進程退出並輸出錯誤日志。
var gulp = require('gulp');
var less = require('gulp-less');
var csso = require('gulp-csso');
var plumber = require('gulp-plumber');
gulp.task('less', function() {
return gulp.src('less/app.less')
.pipe(plumber())
.pipe(less())
.pipe(csso())
.pipe(gulp.dest('./dist'))
});
這比添加錯誤監聽事件省事多了。
stream-combiner2
stream-combiner2 把多個 stream 合並為一個,也就是說只需要添加一個錯誤監聽,相比之下,還是 gulp-plumber 方便。
var combiner = require('stream-combiner2');
var uglify = require('gulp-uglify');
var gulp = require('gulp');
gulp.task('test', function() {
var combined = combiner.obj([
gulp.src('bootstrap/js/*.js'),
uglify(),
gulp.dest('public/bootstrap')
]);
// any errors in the above streams will get caught
// by this listener, instead of being thrown:
combined.on('error', console.error.bind(console));
return combined;
});
