it-swarm.com.ru

Предотвращение ошибок от взлома/сбоя

Я запускаю gulp 3.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)
168
George Mauer

Ваша функция 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'))
})

В качестве альтернативы, если вы не возражаете против включения другого модуля, вы можете использовать функцию loggulp-util, чтобы удержать вас от объявления дополнительной функции в вашей gulpfile :

.on('error', gutil.log)

Но я могу порекомендовать взглянуть на потрясающий плагин gulp-plumber, который используется для удаления обработчика onerror события error, что приводит к разрыву потоков. Он очень прост в использовании и мешает вам поймать все задачи, которые могут быть неудачными.

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

Больше информации об этом на этой статье создателем соответствующего плагина.

253
Balthazar

Приведенные выше примеры не работают для меня. Следующее сделал хотя:

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']);
});
20
user1491819

С одним форматом файлов

(например: * .coffee only)

Если вы хотите работать только с одним форматом файлов, то gulp-plumber - это ваше решение.

Например, ошибки с богатой обработкой и предупреждение для написания кофе:

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 и * .js одновременно)

Но если вы не будете работать с несколькими типами форматов файлов (например: *.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-plumber и gulp-if, используя gulp.watch(...

См. Связанную проблему здесь: 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;

});

P.S .:

Здесь были использованы узлы модулей и функций:

// 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');
};
4
Roman M. Koss

Мне нравится использовать 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

3
Sameeksha Kumari

Простое решение этой проблемы - поместить gulp watch в бесконечный цикл внутри оболочки Bash (или sh).

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

Сохраняйте вывод этой команды в видимой области на экране, пока вы редактируете свой JavaScript. Когда ваши изменения приводят к ошибке, Gulp вылетит, напечатает трассировку стека, подождет секунду и возобновит просмотр ваших исходных файлов. Затем вы можете исправить синтаксическую ошибку, и Gulp укажет, было ли редактирование успешным, либо распечатав его нормальный вывод, либо снова выйдя из строя (затем возобновив).

Это будет работать в терминале Linux или Mac. Если вы используете Windows, используйте Cygwin или Ubuntu Bash (Windows 10).

2
Jesse Hogan

В качестве обходного пути я реализовал следующий хак для 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.

2
Joel Richard

TypeScript

Это то, что сработало для меня. Я работаю с TypeScript и разделил функцию (к путанице в aovid с ключевым словом 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.

NOTE: я пробовал с l.end();; Однако это не сработало. Тем не менее, l.emit('end'); полностью работает.

Надеюсь, это поможет. Удачи.

1
Akash

Это сработало для меня ->

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 (console)) , но мне пришлось запустить команда gulp от имени root. Я запускаю gulp узла в приложении php, поэтому у меня есть несколько учетных записей на одном сервере, поэтому я столкнулся с проблемой взлома gulp из-за синтаксических ошибок, потому что я не запускал gulp от имени root ... Может быть, сантехник и некоторые другие ответы здесь сработали бы для меня, если бы я работал от имени пользователя root Кредит для кода Accio https://www.youtube.com/watch?v=iMR7hq4ABOw для ответа. Он сказал, что, обрабатывая ошибку, она помогает вам определить, в какой строке находится ошибка, и в чем она находится в консоли, но также не дает глотку нарушить синтаксическую ошибку. Он сказал, что это было довольно легкое решение, так что не уверен, что оно подойдет для того, что вы ищете. Быстрое решение, хотя, стоит попробовать. Надеюсь, это поможет кому-то!

0
kiko carisse