GULP: измените отслеживаемый файл на месте, не вызывая бесконечного цикла

Я пытаюсь использовать gulp и jscs, чтобы предотвратить запах кода. Я также хочу использовать часы, чтобы это происходило всякий раз, когда вносятся изменения. Проблема, с которой я сталкиваюсь, заключается в том, что jscs изменяет исходный файл, за которым наблюдают. Это приводит к тому, что gulp входит в бесконечный цикл jsc, изменяющих файл, а затем наблюдает за изменением и запускает jsc снова, снова и снова...

const gulp = require('gulp');

gulp.task('lint', function() {
    return gulp.src('/src/**/*.js')
        .pipe(jscs({
            fix: true
        }))
        .pipe(jscs.reporter())
        .pipe(gulp.dest('/src'));
});

gulp.task('watch', function() {
    gulp.watch('/src/**/*.js', ['lint']);
});

person Jared Christensen    schedule 02.06.2016    source источник


Ответы (1)


Как правило, переопределять исходные файлы из задачи gulp — плохая идея. Любые редакторы / IDE, в которых открыты эти файлы, могут или не могут справиться с этим изящно. Вообще файлы лучше записывать в отдельную папку dist.

При этом есть два возможных решения:

Решение 1

Вам нужно остановить запуск плагина gulp-jscs во второй раз и снова записать файлы, тем самым предотвратив бесконечный цикл, в котором вы работаете. Для этого все, что вам нужно сделать, это добавить gulp-cached к вашей lint задаче:

var cache = require('gulp-cached');

gulp.task('lint', function() {
  return gulp.src('/src/**/*.js')
    .pipe(cache('lint'))
    .pipe(jscs({
        fix: true
    }))
    .pipe(cache('lint'))
    .pipe(jscs.reporter())
    .pipe(gulp.dest('/src'));
});

Первый cache() гарантирует, что пропускаются только те файлы на диске, которые изменились с момента последнего вызова lint. Второй cache() следит за тем, чтобы на диск сначала записывались только те файлы, которые действительно были исправлены jscs().

Недостатком этого решения является то, что задача lint по-прежнему выполняется дважды. Это не имеет большого значения, так как во время второго запуска файлы фактически не анализируются. gulp-cache предотвращает это. Но если вы абсолютно хотите убедиться, что lint запускается только один раз, есть другой способ.

Решение 2

Сначала следует использовать gulp-watch плагин вместо встроенного gulp.watch() (это потому что он использует превосходную библиотеку chokidar вместо gaze).

Затем вы можете написать себе простую функцию pausableWatch() и использовать ее в своей задаче watch:

var watch = require('gulp-watch');

function pausableWatch(watchedFiles, tasks) {
  var watcher = watch(watchedFiles, function() {
    watcher.close();
    gulp.start(tasks, function() {
      pausableWatch(watchedFiles, tasks);
    });
  });
}

gulp.task('watch', function() {
  pausableWatch('/src/**/*.js', ['lint']);
});

В приведенном выше примере watcher останавливается до запуска задачи lint. Поэтому любые файлы .js, записанные во время задачи lint, не вызовут watcher. После завершения задачи lint снова запускается watcher.

Недостатком этого решения является то, что если вы сохраните файл .js во время выполнения задачи lint, это изменение не будет воспринято watcher (поскольку оно было остановлено). Вы должны сохранить файл .js после завершения задачи lint (когда watcher будет запущено снова).

person Sven Schoenung    schedule 03.06.2016
comment
Спасибо, что заглянули! Это исправило бесконечный цикл. Я также хотел бы выяснить, как заставить его запускать задачу только один раз. - person Jared Christensen; 03.06.2016
comment
@JaredChristensen Поскольку кто-то еще спросил в основном тот же вопрос Я еще раз посмотрел на это и нашел альтернативное решение. - person Sven Schoenung; 11.10.2016