防止破碎/撞击手表的错误

我正在运行 Gulp3.6.2,并且有下面的任务,它是从一个在线样本设置的

gulp.task('watch', ['default'], function () {
gulp.watch([
'views/**/*.html',
'public/**/*.js',
'public/**/*.css'
], function (event) {
return gulp.src(event.path)
.pipe(refresh(lrserver));
});


gulp.watch(['./app/**/*.coffee'],['scripts']);
gulp.watch('./app/**/*.scss',['scss']);
});

任何时候我的 CoffeeScript 吞咽表停止出现错误-显然不是我想要的。

正如其他地方推荐的那样,我尝试了这种方法

gulp.watch(['./app/**/*.coffee'],['scripts']).on('error', swallowError);
gulp.watch('./app/**/*.scss',['scss']).on('error', swallowError);
function swallowError (error) { error.end(); }

但好像不管用。

我做错了什么?


为了回应@Aper çu 的回答,我修改了我的 swallowError方法,并尝试了以下方法:

gulp.task('scripts', function () {
gulp.src('./app/script/*.coffee')
.pipe(coffee({ bare: true }))
.pipe(gulp.dest('./public/js'))
.on('error', swallowError);
});

重新启动,然后在我的咖啡文件中创建了一个语法错误。同样的问题:

[gulp] Finished 'scripts' after 306 μs


stream.js:94
throw er; // Unhandled stream error in pipe.
^
Error: W:\bariokart\app\script\trishell.coffee:5:1: error: unexpected *
*
^
at Stream.modifyFile (W:\bariokart\node_modules\gulp-coffee\index.js:37:33)
at Stream.stream.write (W:\bariokart\node_modules\gulp-coffee\node_modules\event-stream\node_modules\through\index.js:26:11)
at Stream.ondata (stream.js:51:26)
at Stream.EventEmitter.emit (events.js:95:17)
at queueData (W:\bariokart\node_modules\gulp\node_modules\vinyl-fs\node_modules\map-stream\index.js:43:21)
at next (W:\bariokart\node_modules\gulp\node_modules\vinyl-fs\node_modules\map-stream\index.js:71:7)
at W:\bariokart\node_modules\gulp\node_modules\vinyl-fs\node_modules\map-stream\index.js:85:7
at W:\bariokart\node_modules\gulp\node_modules\vinyl-fs\lib\src\bufferFile.js:8:5
at fs.js:266:14
at W:\bariokart\node_modules\gulp\node_modules\vinyl-fs\node_modules\graceful-fs\graceful-fs.js:104:5
at Object.oncomplete (fs.js:107:15)
69123 次浏览

你的 swallowError函数应该是这样的:

function swallowError (error) {


// If you want details of the error in the console
console.log(error.toString())


this.emit('end')
}

我认为你必须将这个函数绑定到任务的 error事件上,而不是 watch任务,因为这不是问题所在,你应该在每个可能失败的任务上设置这个错误回调,比如当你错过了 ;或其他任务时插件就会中断,以防 watch任务停止。

例子:

gulp.task('all', function () {
gulp.src('./app/script/*.coffee')
.pipe(coffee({ bare: true }))
.on('error', swallowError)
.pipe(gulp.dest('./public/js'))


gulp.src('css/*.scss')
.pipe(sass({ compass: true }))
.on('error', swallowError)
.pipe(cssmin())
.pipe(gulp.dest('dist'))
})

或者,如果你不介意包含另一个模块,你可以使用 雷尔 = “ noReferrer”> Gulp-util 木头函数来阻止你在你的 gulpfile中声明一个额外的函数:

.on('error', gutil.log)

但是我可能会推荐看一看令人敬畏的 咕噜水管工插件,它用于删除 error事件的 onerror处理程序,从而导致流中断。它使用起来非常简单,并且可以防止您捕获所有可能失败的任务。

gulp.src('./app/script/*.coffee')
.pipe(plumber())
.pipe(coffee({ bare: true }))
.pipe(gulp.dest('./public/js'))

关于 这篇文章的更多信息由相关插件的创建者提供。

使用一种文件格式

(例如: * . 咖啡)

如果您只想处理一种格式的文件,那么 gulp-plumber就是您的解决方案。

例如,rich 处理了咖啡脚本的错误和警告:

gulp.task('scripts', function() {
return gulp.src(['assets/scripts/**/*.coffee'])
.pipe(plumber())
.pipe(coffeelint())
.pipe(coffeelint.reporter())
.pipe(lintThreshold(10, 0, lintThresholdHandler))
.pipe(coffee({
bare: true
}))
.on('error', swallowError)
.pipe(concat('application.js'))
.pipe(gulp.dest('dist/scripts'))
.pipe(rename({ suffix: '.min' }))
.pipe(uglify())
.pipe(gulp.dest('dist/scripts'))
.pipe(notify({ message: 'Scripts task complete' }));
});

具有多种类型的文件格式

(例如: * . coffee and * . js at same time)

但是如果你不想使用多种类型的文件格式(例如: *.js*.coffee) ,那么我将发布我的解决方案。

我只是在这里张贴一个自我解释的代码,以前的一些描述。

gulp.task('scripts', function() {
// plumber don't fetch errors inside gulpif(.., coffee(...)) while in watch process
return gulp.src(['assets/scripts/**/*.js', 'assets/scripts/**/*.coffee'])
.pipe(plumber())
.pipe(gulpif(/[.]coffee$/, coffeelint()))
.pipe(coffeelint.reporter())
.pipe(lintThreshold(10, 0, lintThresholdHandler))
.pipe(gulpif(/[.]coffee$/, coffee({ // if some error occurs on this step, plumber won't catch it
bare: true
})))
.on('error', swallowError)
.pipe(concat('application.js'))
.pipe(gulp.dest('dist/scripts'))
.pipe(rename({ suffix: '.min' }))
.pipe(uglify())
.pipe(gulp.dest('dist/scripts'))
.pipe(notify({ message: 'Scripts task complete' }));
});

我在使用 gulp.watch(...时遇到了 gulp-plumbergulp-if的问题

参见相关问题: https://github.com/floatdrop/gulp-plumber/issues/23

所以对我来说最好的选择是:

  • 每个部分作为文件,并在 后连接。创建多个任务,可以在单独的文件中处理每个部分(就像 grunt 所做的那样) ,并将它们连接起来
  • 每个部分作为流,并在 后合并流。使用 merge-stream(由 event-stream制作)将两个流合并到一个流中,然后继续这个工作(我首先尝试了这个,它对我来说工作得很好,所以它比前一个解决方案更快)

每个部分作为流,并在其后合并流

她是我代码的主要部分:

gulp.task('scripts', function() {
coffeed = gulp.src(['assets/scripts/**/*.coffee'])
.pipe(plumber())
.pipe(coffeelint())
.pipe(coffeelint.reporter())
.pipe(lintThreshold(10, 0, lintThresholdHandler))
.pipe(coffee({
bare: true
}))
.on('error', swallowError);


jsfiles = gulp.src(['assets/scripts/**/*.js']);


return merge([jsfiles, coffeed])
.pipe(concat('application.js'))
.pipe(gulp.dest('dist/scripts'))
.pipe(rename({ suffix: '.min' }))
.pipe(uglify())
.pipe(gulp.dest('dist/scripts'))
.pipe(notify({ message: 'Scripts task complete' }));
});

每个部分作为文件,并连接后

如果要把它分成几个部分,那么在每个部分中都应该创建一个结果文件。例如:

gulp.task('scripts-coffee', function() {


return gulp.src(['assets/scripts/**/*.coffee'])
.pipe(plumber())
.pipe(coffeelint())
.pipe(coffeelint.reporter())
.pipe(lintThreshold(10, 0, lintThresholdHandler))
.pipe(coffee({
bare: true
}))
.on('error', swallowError)
.pipe(concat('application-coffee.js'))
.pipe(gulp.dest('dist/scripts'));


});


gulp.task('scripts-js', function() {


return gulp.src(['assets/scripts/**/*.js'])
.pipe(concat('application-coffee.js'))
.pipe(gulp.dest('dist/scripts'));


});


gulp.task('scripts', ['scripts-js', 'scripts-coffee'], function() {


var re = gulp.src([
'dist/scripts/application-js.js', 'dist/scripts/application-coffee.js'
])
.pipe(concat('application.js'))
.pipe(gulp.dest('dist/scripts'))
.pipe(rename({ suffix: '.min' }))
.pipe(uglify())
.pipe(gulp.dest('dist/scripts'))
.pipe(notify({ message: 'Scripts task complete' }));


del(['dist/scripts/application-js.js', 'dist/scripts/application-coffee.js']);


return re;


});

附言:

这里使用的节点模块和函数:

// Load plugins
var gulp = require('gulp'),
uglify = require('gulp-uglify'),
rename = require('gulp-rename'),
concat = require('gulp-concat'),
notify = require('gulp-notify'),
plumber = require('gulp-plumber'),
merge = require('ordered-merge-stream'),
replace = require('gulp-replace'),
del = require('del'),
gulpif = require('gulp-if'),
gulputil = require('gulp-util'),
coffee = require('gulp-coffee'),
coffeelint = require('gulp-coffeelint),
lintThreshold = require('gulp-coffeelint-threshold');


var lintThresholdHandler = function(numberOfWarnings, numberOfErrors) {
var msg;
gulputil.beep();
msg = 'CoffeeLint failure; see above. Warning count: ';
msg += numberOfWarnings;
msg += '. Error count: ' + numberOfErrors + '.';
gulputil.log(msg);
};
var swallowError = function(err) {
gulputil.log(err.toString());
this.emit('end');
};

我已经为 https://github.com/gulpjs/gulp/issues/71实现了以下黑客技术:

// Workaround for https://github.com/gulpjs/gulp/issues/71
var origSrc = gulp.src;
gulp.src = function () {
return fixPipe(origSrc.apply(this, arguments));
};
function fixPipe(stream) {
var origPipe = stream.pipe;
stream.pipe = function (dest) {
arguments[0] = dest.on('error', function (error) {
var state = dest._readableState,
pipesCount = state.pipesCount,
pipes = state.pipes;
if (pipesCount === 1) {
pipes.emit('error', error);
} else if (pipesCount > 1) {
pipes.forEach(function (pipe) {
pipe.emit('error', error);
});
} else if (dest.listeners('error').length === 1) {
throw error;
}
});
return fixPipe(origPipe.apply(this, arguments));
};
return stream;
}

将它添加到 Gulpfile.js 中,并像这样使用它:

gulp.src(src)
// ...
.pipe(uglify({compress: {}}))
.pipe(gulp.dest('./dist'))
.on('error', function (error) {
console.error('' + error);
});

对我来说,这似乎是最自然的错误处理。如果根本没有错误处理程序,它将抛出一个错误。使用 Node v0.11.13进行测试。

上面的例子对我不起作用,但是下面的例子起作用了:

var plumber = require('gulp-plumber');
var liveReload = require('gulp-livereload');
var gutil = require('gulp-util');
var plumber = require('gulp-plumber');
var compass = require('gulp-compass');
var rename = require('gulp-rename');
var minifycss = require('gulp-minify-css');
var notify = require('gulp-notify');


gulp.task('styles', function () {
//only process main.scss which imports all other required styles - including vendor files.
return gulp.src('./assets/scss/main.scss')
.pipe(plumber(function (error) {
gutil.log(error.message);
this.emit('end');
}))
.pipe(compass({
config_file: './config.rb',
css: './css'
, sass: './assets/scss'
}))
//minify files
.pipe(rename({suffix: '.min'}))
.pipe(minifycss())


//output
.pipe(gulp.dest('./css'))
.pipe(notify({message: 'Styles task complete'}));
});


gulp.task('watch', function () {
liveReload.listen();
gulp.watch('assets/scss/**/*.scss', ['styles']);
});

打印稿

我就是这么做的。我使用 Typescript并分离函数(以避免与 this关键字混淆)来处理 less。这也适用于 Javascript

var gulp = require('gulp');
var less = require('gulp-less');


gulp.task('less', function() {
// writing a function to avoid confusion of 'this'
var l = less({});
l.on('error', function(err) {
// *****
// Handle the error as you like
// *****
l.emit('end');
});


return gulp
.src('path/to/.less')
.pipe(l)
.pipe(gulp.dest('path/to/css/output/dir'))
})

现在,当您的 watch .less文件和 error发生时,watch将不会停止,新的更改将按照您的 less task进行处理。

注意 : 我尝试使用 l.end();; 但是,它不工作。但是,l.emit('end');完全工作。

希望这个能帮上忙,祝你好运。

一个简单的解决方案是将 gulp watch放在 Bash (或 sh) shell 中的无限循环中。

while true; do gulp; gulp watch; sleep 1; done

在编辑 JavaScript 时,将此命令的输出保留在屏幕上的可见区域中。当您的编辑导致一个错误,Gulp 将崩溃,打印其堆栈跟踪,等待一秒钟,并继续观察您的源文件。然后您可以纠正语法错误,Gulp 将通过打印出正常输出或再次崩溃(然后恢复)来指示编辑是否成功。

这将在 Linux 或 Mac 终端上工作。如果您使用 Windows,请使用 Cygwin 或 Ubuntu Bash (Windows10)。

这对我很管用

var gulp = require('gulp');
var sass = require('gulp-sass');


gulp.task('sass', function(){
setTimeout(function(){
return gulp.src('sass/*.sass')
.pipe(sass({indentedSyntax: true}))
.on('error', console.error.bind(console))
.pipe(gulp.dest('sass'));
}, 300);
});






gulp.task('watch', function(){
gulp.watch('sass/*.sass', ['sass']);
});


gulp.task('default', ['sass', 'watch'])

我只是添加了 . on (‘ error’,console. error.bind (sole)) 但是我不得不运行 吞下去 命令作为 root 用户。我在一个 php 应用程序上运行 node Gulp,所以我在一个服务器上有多个帐户,这就是为什么我遇到了语法错误的 Gulp 中断问题,因为我没有以 root 用户的身份运行 Gulp... ... 如果我以 root 用户的身份运行的话,也许 Plubber 和这里的其他一些答案会对我有用。 答案来自 Accio Code https://www.youtube.com/watch?v=iMR7hq4ABOw。他说,通过处理错误,它可以帮助您确定错误所在的行和控制台中的错误,而且还可以防止语法错误导致的断开。他说,这是一种轻量级的修复,所以不确定它是否会工作,你正在寻找。不过速战速决,值得一试。希望这对谁有帮助!

我喜欢使用 Gulp Plumber,因为它可以为任务添加一个全局监听器,并显示有意义的消息。

var plumber = require('gulp-plumber');


gulp.task('compile-scss', function () {
gulp.src('scss/main.scss')
.pipe(plumber())
.pipe(sass())
.pipe(autoprefixer())
.pipe(cssnano())
.pipe(gulp.dest('css/'));
});

参考资料: https://scotch.io/tutorials/prevent-errors-from-crashing-gulp-watch