Выявление ошибок на Gulp.js
Режим просмотра важен для современных систем сборки, особенно для интерфейсной части. Gulp также имеет эту функцию, но с некоторыми оговорками, которые усложняют работу. Это потоковая система сборки, поэтому вам придется иметь дело с Steam API, где вы должны перехватывать каждую ошибку, иначе будет выброшено неперехваченное исключение, которое остановит процесс сборки.
Это особенно важно для наблюдателя, потому что демон watch живет долгое время, и это нехорошо, когда неперехваченная ошибка убивает его.
В чем дело?
Прежде всего, нам нужно выяснить, почему это происходит, почему наблюдатель иногда дает сбой и умирает. Рекомендуемый способ уведомления о произошедших ошибках в плагинах gulp - это выдача события error. Но потоки node.js, которые фактически используются в gulp, не позволяют оставлять ошибки незамеченными. Если в каком-либо потоке нет слушателей на событие `error`, в случае ошибки будет сгенерировано необработанное исключение. Это должно было быть уверенным, что сообщение об ошибке из потока дошло до пользователей. В результате при работе с gulp разработчики часто видят в консоли следующую ошибку:
events.js:72 throw er; // Unhandled ‘error’ event
Пока вы запускаете сборку на сервере непрерывной интеграции, такое поведение может быть полезно, оно помогает отлавливать ошибки. Но это ошибки при локальной разработке с наблюдателем, которые могут раздражать, потому что наблюдатель всегда нужно перезапускать.
Что делать?
По этому поводу ведется много дискуссий, например, о stackoverflow. Также есть проблема на Github в репозитории gulp. Предлагаются некоторые решения.
Во-первых, подпишитесь на событие ошибки и не позволяйте генерировать необработанное исключение:
gulp.task('less', function() { return gulp.src('less/*.less') .pipe(less().on('error', gutil.log)) .pipe(gulp.dest('app/css')); });
Затем вы можете использовать плагин gulp-plumber, который подавляет обработчик ошибок по умолчанию для всех последующих плагинов в цепочке pipe ().
gulp.task('less', function() { return gulp.src('less/*.less') .pipe(plumber()) .pipe(less()) .pipe(gulp.dest('app/css')); });
Зачем понадобилось другое решение?
Несмотря на то, что проблема выглядит решенной, это не так. Теперь вы не будете получать никаких сообщений об ошибках при сборке на CI-сервере. Все ошибки теперь где-то фиксируются, поэтому gulp думает, что все задачи были выполнены правильно, даже если возникли некоторые ошибки. Компьютеры не могут читать и понимать вывод консоли, они используют коды выхода, чтобы сообщить результат процесса, и в этом случае код выхода равен нулю, что означает «успех». И теперь у нас есть вопрос, как вернуть наши обработчики ошибок.
Правильное получение ошибок
Фактически, gulp может получать ошибки из конвейера. Но только от последнего в цепочке, потому что потоки предназначены для того, чтобы не распространять ошибки по каналам. В репозитории Node.js есть пул-реквест с соответствующим предложением, но он еще не объединен. Итак, теперь gulp может получить только ошибку из последнего потока, и обычно это вызов gulp.dest () для записи результата задачи в файл. Но обычно ошибки возникают в других подключаемых модулях между gulp.src и dest. Глоток их не видит, но мы можем ему помочь.
В результате функция задачи Gulp может принимать не только потоки. Мы можем определить задачу в классическом стиле узла с обратным вызовом в аргументах. Эту функцию мы можем вызывать вручную и сообщать об ошибках из средних каналов.
gulp.task('less', function(done) { gulp.src('less/*.less') .pipe(less()).on('error', function(error) { // we have an error done(error); }) .pipe(gulp.dest(‘app/css’)) .on(‘end’, function() { // in case of success done(); }); });
Таким образом можно обрабатывать ошибки более подробно, но правильно. Мы можем переместить общий код в небольшую вспомогательную функцию, как в этой сути, и тогда мы получим меньше кода в определении задачи:
gulp.task(‘less’, wrapPipe(function(success, error) { return gulp.src(‘less/*.less’) .pipe(less().on(‘error’, error)) .pipe(gulp.dest(‘app/css’)); }));
Теперь мы можем спокойно относиться к нашей сборке на CI-сервере, а также наслаждаться локальной разработкой.