typescript - Gulp-watch avslutas eller bygger hela uppgiftskedjan


Jag utvecklar ett TypeScript-projekt med följande byggsteg:

  • ludd
  • bygga
  • test

Jag använder Gulp 4.0 som ett byggverktyg och vill ha en watch-uppgift, som ska trigga testet (vilket innebär att lint- och build-uppgifter triggas innan). För närvarande, när ett fel uppstår (till exempel ett lint-fel), avslutas watch-uppgiften.

Detta problem är välkänt och lätt att lösa. Den typiska lösningen är a) att förebygga fel eller b) att åtgärda rörbeteendet.

a) För gulp-tslint kunde jag använda den här konfigurationen från deras hemsida:

gulp.task("invalid-noemit", () =>
    gulp.src("input.ts")
        .pipe(tslint())
        .pipe(tslint.report("prose", {
          emitError: false
        }))
);

Men när jag inkluderar emitError-flaggan, loggas lint-felen och alla efterföljande gulp-uppgifter utförs (build, test).

b) Jag skulle också kunna använda gulp-plumber eller fånga fel manuellt (se här), men beteendet är detsamma för alla dessa kända lösningar, följande gulp-uppgifter körs (build, test).

Det jag vill är att uppgiftskedjan ska stoppas efter ett fel (ingen bygg och test efter ett lint-fel), men bevakningsuppgiften ska aldrig sluta. Hur skulle jag kunna lösa detta? Bevakningsuppgifterna ser ut så här:

// watcher
gulp.task('watch', gulp.series('test', function doWatch() {
    gulp.watch([
        config.paths.sourcePattern,
        config.paths.testPattern,
        'gulpfile.js'
    ], gulp.parallel('test'));
}));

:

Svar #1

Anledningen till att din klocka stannar är att ett err-objekt sprids uppåt i callback-kedjan. Du måste förhindra att det err når den sista gulp.watch()-callbacken.

Du kan göra det genom att omsluta callbacken som tillhandahålls av gulp.watch() och aldrig skicka err-objektet vidare till den ursprungliga callbacken:

gulp.task('watch', function() {
  gulp.watch([
      config.paths.sourcePattern,
      config.paths.testPattern,
      'gulpfile.js'
    ], {ignoreInitial:false}, function(cb) {
      gulp.series('lint', 'build', 'test')(function wrappedCb(err) {
        cb(); // not passing err here
    });
  });
});

Observera att gulp.series('lint', 'build', 'test') inte faktiskt kör uppgifterna. Det returnerar bara en ny funktion som accepterar en återuppringning. Först när denna nya funktion anropas som gulp.series('lint', 'build', 'test')() körs uppgifterna faktiskt.

Jag lade också till alternativet ignoreInitial så att övervakningen körs en gång efter uppstarten, vilket verkar vara vad du försöker uppnå med gulp.series('test', ...) i din watch-uppgift.

(Sidokommentar: att övervaka gulpfile.js är meningslöst. Ändringar i din gulpfile kommer inte att träda i kraft förrän du kör gulp watch igen. Det finns inget sätt runt detta.)

Slutligen behöver du koppla bort dina andra uppgifter, så att de inte har explicita beroenden på andra uppgifter. Det är frestande att översätta en gulp 3.x-uppgift på detta sätt:

gulp.task('foo', ['bar'], function() { });

In i en gulp 4.x-uppgift som denna:

gulp.task('foo', gulp.series('bar', function() { }));

De ser liknande ut på ytan, men de är helt olika under huven. Se den här artikeln för mer om det ämnet.

En bra strategi är att organisera dina uppgifter i två kategorier:

  1. Fristående uppgifter som gör en sak och inte är beroende av andra uppgifter.
  2. Sammansatta uppgifter som kör flera andra uppgifter i serie eller parallellt.

Följande princip kan dina andra uppgifter omstruktureras till detta:

gulp.task('lint', function() {
  return gulp.src([
    config.paths.sourcePattern,
    config.paths.testPattern
  ])
  .pipe(tslint())
  .pipe(tslint.report('verbose', {
    emitError: true, // we WANT to emit this err so our other tasks don't run
    summarizeFailureOutput: true
  }));
});

gulp.task('build-app', function doBuildApp() {
  /* ... */
});

gulp.task('build-test', function doBuildTest() {
  /* ... */
});

gulp.task('build', gulp.series('lint', 'build-app', 'build-test'));

gulp.task('test', gulp.series(function doPreTest() {
    /* ... */
  }, function doTest() {
    /* ... */
  }, function doPostTest() {
    /* ... */
}));

Relaterade artiklar