web-dev-qa-db-ja.com

エラーがgulpウォッチを壊したりクラッシュさせないようにする

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)
173
George Mauer

swallowErrorname__関数は次のようになります。

function swallowError (error) {

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

  this.emit('end')
}

errorname__タスクではなく、落下していたタスクのwatchname__イベントでこの関数をバインドする必要があると思います。問題はどこにあるかではないため、失敗する可能性のある各タスクでこのエラーコールバックを設定する必要があります。 watchname__タスクが停止するのを防ぐために、;または他の何かを見逃しています。

例:

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関数を使用できます。 gulpfilename__で追加の関数を宣言しないようにします。

.on('error', gutil.log)

しかし、素晴らしいgulp-plumberプラグインをご覧になることをお勧めします。このプラグインは、onerrorname__イベントのerrorname__ハンドラーを削除して、ブレークを引き起こしますストリームの。使い方はとても簡単で、失敗する可能性のあるすべてのタスクをキャッチできなくなります。

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

このプラグインの作成者による この記事 の詳細について。

254
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

1つのファイル形式

(例:* .coffeeのみ)

1つの形式のファイルのみを処理したい場合は、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-plumbergulp-ifを使用して、gulp.watch(...を使用して問題に直面しました

関連する問題はこちら: https://github.com/floatdrop/gulp-plumber/issues/2

だから私にとって最良の選択肢は:

  • 各部分をファイルとして、後に連結します。個別のファイル内の各部分を処理できる複数のタスクを作成し(Gruntと同じように)、それらを連結します
  • 各部分をストリームとして、の後にストリームをマージします。 merge-streamevent-streamから作成された)を使用して2つのストリームを1つにマージし、ジョブを続行します(最初にそれを試しました。

ストリームとしての各部分、およびその後のストリームのマージ

彼女は私のコードの主要部分です:

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

これの簡単な解決策は、gulp watchをBash(またはsh)シェル内の無限ループに入れることです。

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

JavaScriptの編集中は、このコマンドの出力を画面上の表示領域に保持してください。編集結果がエラーになると、Gulpはクラッシュし、スタックトレースを出力し、1秒待ってからソースファイルの監視を再開します。その後、構文エラーを修正できます。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を操作し、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に従って新しい変更が処理されます。

NOTEl.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コマンドをルートとして実行する必要がありました。私はphpアプリケーションでnode gulpを実行していますので、1つのサーバーに複数のアカウントがあります。私がルートとして実行した場合、ここでの他の答えは私のために働いていただろう。 Accio Codeのクレジット https://www.youtube.com/watch?v=iMR7hq4ABOw 回答。彼は、エラーを処理することで、エラーがどの行にあり、コンソールに何があるのか​​を判断するのに役立つが、gulpが構文エラーで中断するのを防ぐとも言った。彼はそれが一種の軽量修正であると言ったので、それがあなたが探しているものにうまくいくかどうかはわかりません。しかし、一応の価値があるクイックフィックス。これが誰かを助けることを願っています!

1
kiko carisse