Gulp 시계가 깨지거나 충돌하는 것을 방지


178

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 시계에 오류가 발생하면 언제든지 내가 원하는 것이 아닙니다.

다른 곳에서 추천했듯이 이것을 시도했습니다.

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)

3
github.com/gulpjs/gulp/tree/master/docs/recipes 에서 공식 gulp 레시피를 참조하십시오 .
danday74

답변:


257

귀하의 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'))
})

또는 다른 모듈을 포함하지 않으려는 경우 gulp-utillog 함수를 사용하여 추가 함수를 선언하지 못하게 할 수 있습니다 .gulpfile

.on('error', gutil.log)

그러나 이벤트 처리기 를 제거 하여 스트림이 중단 되는 멋진 gulp-plumber 플러그인을 살펴 보는 것이 좋습니다 . 사용이 매우 간단하고 실패 할 수있는 모든 작업을 잡을 수 없습니다.onerrorerror

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

관련 플러그인의 작성자 가이 기사 에 대한 자세한 정보를 제공합니다 .


도와 주셔서 감사합니다. 내 편집을 참조하십시오. 나는 당신이 말하는 것을하고 있다고 생각하는데 여전히 작동하지 않습니다.
George Mauer

2
최종적으로 올바른 것을 반영하기 위해 답을 편집하고 싶을 수도 있습니다. 나중에 이것을 발견하는 사람은 주석 체인을 읽을 필요가 없습니다.
George Mauer

1
이것은 모두 훌륭하지만 왜 내 자신의 오류 처리기를 작성해야합니까? 내가 꿀꺽 꿀꺽 또는 grunt 또는 전처리 도구를 사용하는 모든 이유는 그것이 나를 위해 더러운 일을하기 때문입니다. 내 코드 어딘가에 구문 오류가 발생하면 전체 시스템이 중단되지 않아야합니다. 이 도구를 Prepros (다른 전 처리기)의 GUI와 비교하십시오.이 도구는 오류가 발생한 위치를 정확하게 알려주고 무언가 잘못되었을 때 멈추거나 종료되지 않습니다.
Kokodoko

1
비록 공식 꿀꺽 꿀꺽 조리법 임에도 불구하고 스팀 컴 비너 2를 언급 한 사람은 아무도 없습니다. 배관공도 좋지만 항상 gulp
danday74

1
같은 수수께끼에 직면하여, 나는 시계 기능의 결과에 gulp.watch()추가되는 래퍼를 사용하기로 결정했습니다. .on('error', function() { this.emit('end') })왜냐하면 그것은 특히 전화 끊기에 탄력적으로 만들고 싶은 시계 작업이기 때문입니다. 실제로 잘 작동하며 실패한 개별 작업은 여전히 ​​자체 오류 메시지를 인쇄합니다. 코드를 참조하십시오 : github.com/specious/specious.github.io/commit/f8571d28
tknomad

20

위의 예제는 저에게 효과적이지 않았습니다. 그러나 다음은 수행했습니다.

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

이것은 훌륭하지만 오류가있는 경우 알려주는 것이 좋습니다 (현재는 터미널에 오류를 기록합니다)
raison

4

한 가지 형식의 파일

(예 : *. 커피 만)

한 가지 형식의 파일로만 작업하려면 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-ifgulp.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;

});

추신:

사용 된 노드 모듈 및 기능은 다음과 같습니다.

// 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');
};

나는 여전히이 의견에 대한 개선을 본다. 속도 비교와 마찬가지로 .js 파일의 링크 만 (축소 또는 타사 라이브러리 또는 bower_components의 lib 제외). 그러나 기본적으로 Google.com이 스니핑을 쉽게 조정하고 해결할 수 있습니다
Roman M. Koss

3

나는 gulp 배관공을 사용하여 작업에 전역 리스너를 추가하고 의미있는 메시지를 표시 할 수 있기 때문에 사용하고 싶습니다.

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


2

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);
    });

이것은 나에게 가장 자연스러운 오류 처리처럼 느껴집니다. 오류 처리기가 전혀 없으면 오류가 발생합니다. 노드 v0.11.13으로 테스트되었습니다.


2

이것에 대한 간단한 해결책 gulp watch은 Bash (또는 sh) 쉘 내에 무한 루프 를 넣는 것 입니다.

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

JavaScript를 편집 할 때이 명령의 출력을 화면의 보이는 영역에 유지하십시오. 편집 결과 오류가 발생하면 Gulp는 충돌을 일으켜 스택 추적을 인쇄하고 잠시 기다렸다가 소스 파일보기를 다시 시작합니다. 그런 다음 구문 오류를 정정 할 수 있으며 Gulp는 편집 결과가 정상 출력인지 또는 다시 크래시 (다시 시작)하여 성공했는지 여부를 나타냅니다.

이것은 Linux 또는 Mac 터미널에서 작동합니다. Windows를 사용하는 경우 Cygwin 또는 Ubuntu Bash (Windows 10)를 사용하십시오.


이것이 무슨 언어 지? 또한 제안 된 솔루션보다 이점이 있습니까?
George Mauer

Bash / sh로 작성되었습니다. 다른 솔루션보다 적은 코드가 필요하며 기억하고 구현하기가 더 쉽습니다.
Jesse Hogan

그것의 bash와 이것에 대한 당신의 다른 생각이 당신의 대답에 있다는 사실을 편집 할 수 있습니까? 나는 배관공이 쉽지만 배관공이 아니라면 유효한 방법이라고 동의하지 않습니다. 사용 언어가 확실하지 않기 때문에 처음에 투표를했습니다. 답변을 수정하지 않으면 투표를 변경할 수 없습니다.
George Mauer

1
따라서 스트림을 크래쉬하고 전체 프로세스를 다시 시작하는 것을 선호합니다. 단순히 오류를 잡는 것이 아니라 무한 루프로 수행중인 작업에 따라 꽤 많은 시간이 걸릴 수 있습니까? 나에게 조금 혼란스러워 보인다. 코드가 적기 때문에 작업에 배관공을 추가하려면 16 문자가 필요하지만 솔루션은 계산하지 않고 36을 사용합니다 gulp watch.
Balthazar

피드백, @GeorgeMauer에 감사드립니다, 나는 편집하고 그것이 작동하는 환경 / 플랫폼에 대해 썼습니다.
Jesse Hogan

1

타이프 스크립트

이것이 나를 위해 일한 것입니다. 처리 Typescript하는 기능 ( this키워드 와의 혼란을 aovid 하기 위해)으로 작업 하고 분리했습니다 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'); 완전히 작동합니다.

이 도움을 바랍니다. 행운을 빕니다.


1

이것은 나를 위해 일했다->

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 명령을 루트로 실행해야했습니다. PHP 응용 프로그램에서 node gulp를 실행 중이므로 한 서버에 여러 계정이 있으므로 gulp를 루트로 실행하지 않았기 때문에 구문 오류가 발생하는 gulp 문제가 발생했습니다 ... 아마도 배관공과 일부는 내가 루트로 달린다면 여기에 다른 답변이 효과가 있었을 것입니다. 정답은 Accio Code https://www.youtube.com/watch?v=iMR7hq4ABOw 입니다. 그는 오류를 처리함으로써 오류가 어느 라인에 있는지, 콘솔에 무엇이 있는지를 결정하는 데 도움이되지만, 문법 오류로 인해 꿀꺽 꿀꺽하는 것도 막을 수 있다고 말했다. 그는 그것이 가벼운 무게의 일종이라고 말했기 때문에 그것이 당신이 찾고있는 것에 효과가 있는지 확실하지 않습니다. 그러나 빠른 수정은 가치가 있습니다. 이것이 누군가를 돕기를 바랍니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.