Gulp.js stops compiling LESS when watched after th

2019-03-18 14:46发布

问题:

I'm having a problem with gulp. I run gulp-watch along with gulp-less and gulp-clean. Everything is running perfectly.

When I edit somefile.less and I save it with a semi-colon missing or maybe I accidentally leave a trailing ;s, just have errors in my code when saving, gulp-less logs an error in the console. After I fix it gulp-watch continues watching the files, but gulp-less doesn't fire and it doesn't compile. When I stop gulp and run it again in the terminal everything goes back to normal.

Here is my gulpfile.js:

var gulp = require('gulp');
var clean = require('gulp-clean');
var gutil = require('gulp-util');
var less = require('gulp-less');
var watch = require('gulp-watch');
var path = require('path');

gulp.task('clean', function() {
    return gulp.src('src/main/webapp/styles/build', {read: false})
   .pipe(clean().on('error', gutil.log))
});

gulp.task('less', function() {
    return gulp.src(['src/main/webapp/styles/main.less'], {base: 'src/main/webapp/styles/'})
    .pipe(less().on('error', gutil.log))
    .pipe(gulp.dest('src/main/webapp/styles/build'))
    .on('error', gutil.log);
});

gulp.task('watch', function() {
    watch('src/main/webapp/styles/**/*.{less, css}', function() {
        gulp.start('less')
        .on('error', gutil.log);
    })
});

gulp.task('default', ['clean'], function() {
    gulp.start(['less', 'watch'])
    .on('error', gutil.log);
});

And here are my devDependencies:

"devDependencies": {
    "gulp": "^3.8.10",
    "gulp-clean": "^0.3.1",
    "gulp-less": "^2.0.1",
    "gulp-util": "^3.0.2",
    "gulp-watch": "^3.0.0"
}

Finally, here is the message in the console:

[10:21:03] imports/productSearchPage.less was changed
[10:21:03] Starting 'less'...
[10:21:03] { [Error: Unrecognised input. Possibly missing something in file /src/main/webapp/styles/imports/productSearchPage.less line no. 1008]
  type: 'Parse',
  filename: '/src/main/webapp/styles/imports/productSearchPage.less',
  index: 19127,
  line: 1008,
  callLine: NaN,
  callExtract: undefined,
  column: 0,
  extract: [ '', '', undefined ],
  message: 'Unrecognised input. Possibly missing something in file /src/main/webapp/styles/imports/productSearchPage.less line no. 1008',
  stack: undefined,
  lineNumber: 1008,
  fileName: '/src/main/webapp/styles/imports/productSearchPage.less',
  name: 'Error',
  showStack: false,
  showProperties: true,
  plugin: 'gulp-less',
  __safety: { toString: [Function] } }
[10:21:04] imports/productSearchPage.less was changed
[10:21:08] imports/productSearchPage.less was changed
^C

Can you please tell me what is wrong with the gulp-watch task and help me make it run gulp-less after the errors have been removed, without restarting gulp.

EDIT: My edited gulp-less task

gulp.task('less', function() {
    return gulp.src(['src/main/webapp/styles/main.less'], {base: 'src/main/webapp/styles/'})
    .pipe(less().on('error', gutil.log))
    .pipe(gulp.dest('src/main/webapp/styles/build'))
    .on('error', function(err) {
        gutil.log(err);
        this.emit('end');
    });
});

回答1:

It works now! Here is my final, and working, gulp-less task:

gulp.task('less', function() {
    return gulp.src(['src/main/webapp/styles/main.less'], {base: 'src/main/webapp/styles/'})
    .pipe(less().on('error', function(err){
        gutil.log(err);
        this.emit('end');
    }))
    .pipe(gulp.dest('src/main/webapp/styles/build'))
});

The problem was that, when there was an error in the LESS the task still went on and built the destination file. On top of that I placed the error logging function and the emit('end') as a callback to gulp.dest.

Now, when the callback of less() is the error log and emit('end') everything works perfectly.



回答2:

I always use gulp-plumber for my error catching. Works really easily and logs the error to the console.

Example:

gulp.task('less', function() {
    return gulp.src(['src/main/webapp/styles/main.less'], {base: 'src/main/webapp/styles/'})
    .pipe(plumber())
    .pipe(less().on('error', gutil.log))
    .pipe(gulp.dest('src/main/webapp/styles/build'))
    .on('error', function(err) {
        gutil.log(err);
        this.emit('end');
    });
});


回答3:

I have just set this up for my own personal project. According to the Gulp docs, you can just use gulp.watch:

gulp.task('watch', function() {
    gulp.watch('src/main/webapp/styles/**/*.{less, css}', ['less'])
        .on('error', gutil.log);
});

EDIT: If this doesn't help, change your less task to:

gulp.task('less', function() {
    return gulp.src(['src/main/webapp/styles/main.less'], {base: 'src/main/webapp/styles/'})
    .pipe(less())
    .on('error', function (err) {
        gutil.log(err);
        this.emit('end');
    })
    .pipe(gulp.dest('src/main/webapp/styles/build'))
    .on('error', gutil.log);
});

Adapted from this comment.



回答4:

the best solution I have tried; https://github.com/gulpjs/gulp/blob/master/docs/recipes/combining-streams-to-handle-errors.md

var combiner = require('stream-combiner2');
gulp.task('multi:less', function(done) {
    var combined = combiner.obj([
        gulp.src(srcs),
        less(),
        autoprefixer({
            browsers: ['last 6 versions'],
            cascade: false
        }),
        isDev ? null : cleanCss(),
        gulp.dest(targetDir + 'css/multi/'),
    ].filter(v => v));

    // any errors in the above streams will get caught
    // by this listener, instead of being thrown:
    combined.on('error', console.error.bind(console));
    combined.on('end', () => {}); //done have been call when return combined;
    return combined;

}