javascript - Cómo ejecutar las tareas de Gulp secuencialmente una tras otra
node.js coffeescript (13)
Aún no es una versión oficial, pero el Gulp 4.0 que se avecina le permite realizar fácilmente tareas sincrónicas con gulp.series. Simplemente puedes hacerlo así:
gulp.task(''develop'', gulp.series(''clean'', ''coffee''))
Encontré una buena publicación en el blog que presenta cómo actualizar y hacer un uso de esas características ordenadas: migrar a gulp 4 por ejemplo
en el fragmento de esta manera:
gulp.task "coffee", ->
gulp.src("src/server/**/*.coffee")
.pipe(coffee {bare: true}).on("error",gutil.log)
.pipe(gulp.dest "bin")
gulp.task "clean",->
gulp.src("bin", {read:false})
.pipe clean
force:true
gulp.task ''develop'',[''clean'',''coffee''], ->
console.log "run something else"
En la tarea de develop
, quiero correr clean
y, una vez hecho, coffee
y, cuando haya terminado, ejecutar otra cosa. Pero no puedo entender eso. Esta pieza no funciona. Por favor avise.
De forma predeterminada, gulp ejecuta tareas simultáneamente, a menos que tengan dependencias explícitas. Esto no es muy útil para tareas como clean
, donde no desea depender, pero necesita que se ejecuten antes que cualquier otra cosa.
Escribí el complemento de run-sequence
específicamente para solucionar este problema con gulp. Después de instalarlo, úsalo así:
var runSequence = require(''run-sequence'');
gulp.task(''develop'', function(done) {
runSequence(''clean'', ''coffee'', function() {
console.log(''Run something else'');
done();
});
});
Puede leer las instrucciones completas en el paquete README; también admite la ejecución de algunos conjuntos de tareas simultáneamente.
Tenga en cuenta que esto se solucionará (efectivamente) en la próxima versión importante de Gulp , ya que eliminan por completo el pedido automático de dependencias y brindan herramientas similares a run-sequence
para permitirle especificar manualmente el orden de ejecución que desee.
Sin embargo, ese es un cambio importante, por lo que no hay razón para esperar cuando se puede usar run-sequence
hoy.
Estaba teniendo exactamente el mismo problema y la solución resultó ser bastante fácil para mí. Básicamente cambia tu código a lo siguiente y debería funcionar. NOTA: la devolución antes de gulp.src hizo toda la diferencia para mí.
gulp.task "coffee", ->
return gulp.src("src/server/**/*.coffee")
.pipe(coffee {bare: true}).on("error",gutil.log)
.pipe(gulp.dest "bin")
gulp.task "clean",->
return gulp.src("bin", {read:false})
.pipe clean
force:true
gulp.task ''develop'',[''clean'',''coffee''], ->
console.log "run something else"
Estuve buscando esta respuesta por un tiempo. Ahora lo tengo en la documentación oficial.
Si desea realizar una tarea truculenta cuando se completa la última, debe devolver una secuencia:
gulp.task(''wiredep'', [''dev-jade''], function () {
var stream = gulp.src(paths.output + ''*.html'')
.pipe($.wiredep())
.pipe(gulp.dest(paths.output));
return stream; // execute next task when this is completed
});
// First will execute and complete wiredep task
gulp.task(''prod-jade'', [''wiredep''], function() {
gulp.src(paths.output + ''**/*.html'')
.pipe($.minifyHtml())
.pipe(gulp.dest(paths.output));
});
Generé una aplicación node / gulp usando el generator-gulp-webapp Yeoman de generator generator-gulp-webapp . Manejó el "enigma limpio" de esta manera (traduciendo a las tareas originales mencionadas en la pregunta):
gulp.task(''develop'', [''clean''], function () {
gulp.start(''coffee'');
});
Gulp y Node usan promesas .
Así que puedes hacer esto:
// ... require gulp, del, etc
function cleanTask() {
return del(''./dist/'');
}
function bundleVendorsTask() {
return gulp.src([...])
.pipe(...)
.pipe(gulp.dest(''...''));
}
function bundleAppTask() {
return gulp.src([...])
.pipe(...)
.pipe(gulp.dest(''...''));
}
function tarTask() {
return gulp.src([...])
.pipe(...)
.pipe(gulp.dest(''...''));
}
gulp.task(''deploy'', function deployTask() {
// 1. Run the clean task
cleanTask().then(function () {
// 2. Clean is complete. Now run two tasks in parallel
Promise.all([
bundleVendorsTask(),
bundleAppTask()
]).then(function () {
// 3. Two tasks are complete, now run the final task.
tarTask();
});
});
});
Si devuelve la secuencia Gulp, puede usar el método then()
para agregar una devolución de llamada. Alternativamente, puede usar la Promise
nativa de Node para crear sus propias promesas. Aquí utilizo Promise.all()
para tener una devolución de llamada que se Promise.all()
cuando se resuelven todas las promesas.
La única buena solución a este problema se puede encontrar en la documentación de Gulp que se puede encontrar here
var gulp = require(''gulp'');
// takes in a callback so the engine knows when it''ll be done
gulp.task(''one'', function(cb) {
// do stuff -- async or otherwise
cb(err); // if err is not null and not undefined, the orchestration will stop, and ''two'' will not run
});
// identifies a dependent task must be complete before this one begins
gulp.task(''two'', [''one''], function() {
// task ''one'' is done now
});
gulp.task(''default'', [''one'', ''two'']);
// alternatively: gulp.task(''default'', [''two'']);
Para mí, no estaba ejecutando la tarea minify después de la concatenación, ya que espera una entrada concatenada y no se generó algunas veces.
Intenté agregar una tarea predeterminada en el orden de ejecución y no funcionó. Funcionó después de agregar solo un return
para cada tarea y obtener la gulp.start()
dentro de gulp.start()
como se muestra a continuación.
/**
* Concatenate JavaScripts
*/
gulp.task(''concat-js'', function(){
return gulp.src([
''js/jquery.js'',
''js/jquery-ui.js'',
''js/bootstrap.js'',
''js/jquery.onepage-scroll.js'',
''js/script.js''])
.pipe(maps.init())
.pipe(concat(''ux.js''))
.pipe(maps.write(''./''))
.pipe(gulp.dest(''dist/js''));
});
/**
* Minify JavaScript
*/
gulp.task(''minify-js'', function(){
return gulp.src(''dist/js/ux.js'')
.pipe(uglify())
.pipe(rename(''ux.min.js''))
.pipe(gulp.dest(''dist/js''));
});
gulp.task(''concat'', [''concat-js''], function(){
gulp.start(''minify-js'');
});
gulp.task(''default'',[''concat'']);
Probé todas las soluciones propuestas, todas parecen tener problemas propios.
Si realmente busca en el origen del orquestador, particularmente en la implementación de .start()
verá que si el último parámetro es una función, lo tratará como una devolución de llamada.
Escribí este fragmento para mis propias tareas:
gulp.task( ''task1'', () => console.log(a) )
gulp.task( ''task2'', () => console.log(a) )
gulp.task( ''task3'', () => console.log(a) )
gulp.task( ''task4'', () => console.log(a) )
gulp.task( ''task5'', () => console.log(a) )
function runSequential( tasks ) {
if( !tasks || tasks.length <= 0 ) return;
const task = tasks[0];
gulp.start( task, () => {
console.log( `${task} finished` );
runSequential( tasks.slice(1) );
} );
}
gulp.task( "run-all", () => runSequential([ "task1", "task2", "task3", "task4", "task5" ));
Prueba este hack :-) Gulp v3.x Hack para Async bug
Probé todas las formas "oficiales" en el archivo Léame, no funcionaron para mí, pero esto sí. También puedes actualizar a Gulp 4.x, pero te recomiendo que no lo hagas, se rompe muchas cosas. Podría usar una promesa js real, pero bueno, esto es rápido, sucio, simple :-) Esencialmente usa:
var wait = 0; // flag to signal thread that task is done
if(wait == 0) setTimeout(... // sleep and let nodejs schedule other threads
Echa un vistazo a la publicación!
Según los documentos de Gulp:
¿Se ejecutan sus tareas antes de que se completen las dependencias? Asegúrese de que sus tareas de dependencia estén utilizando correctamente las sugerencias de ejecución asíncronas: reciba una devolución de llamada o devuelva una promesa o flujo de eventos.
Para ejecutar su secuencia de tareas de forma síncrona:
- Devuelva la secuencia de eventos (por ejemplo,
gulp.src
) agulp.task
para informar a la tarea de cuándo finaliza la secuencia. - Declare las dependencias de la tarea en el segundo argumento de
gulp.task
.
Ver el código revisado:
gulp.task "coffee", ->
return gulp.src("src/server/**/*.coffee")
.pipe(coffee {bare: true}).on("error",gutil.log)
.pipe(gulp.dest "bin")
gulp.task "clean", [''coffee''], ->
return gulp.src("bin", {read:false})
.pipe clean
force:true
gulp.task ''develop'',[''clean'',''coffee''], ->
console.log "run something else"
Simplemente haga que el coffee
dependa de la clean
y develop
dependa del coffee
:
gulp.task(''coffee'', [''clean''], function(){...});
gulp.task(''develop'', [''coffee''], function(){...});
El envío ahora es serial: clean
→ coffee
→ develop
. Tenga en cuenta que la implementación de clean
y la implementación de coffee
deben aceptar una devolución de llamada, "para que el motor sepa cuándo se realizará" :
gulp.task(''clean'', function(callback){
del([''dist/*''], callback);
});
En conclusión, a continuación se muestra un sencillo patrón trucado para una clean
sincrónica seguida de dependencias de compilación asíncronas :
//build sub-tasks
gulp.task(''bar'', [''clean''], function(){...});
gulp.task(''foo'', [''clean''], function(){...});
gulp.task(''baz'', [''clean''], function(){...});
...
//main build task
gulp.task(''build'', [''foo'', ''baz'', ''bar'', ...], function(){...})
Gulp es lo suficientemente inteligente como para ejecutarse clean
una vez por build
, sin importar cuántas dependencias de build
dependan de la clean
. Como se escribió anteriormente, clean
es una barrera de sincronización, entonces todas las dependencias de build
ejecutan en paralelo, luego la build
ejecuta.
La secuencia de ejecución es la forma más clara (al menos hasta que se libere Gulp 4.0)
Con la secuencia de ejecución , tu tarea se verá así:
var sequence = require(''run-sequence'');
/* ... */
gulp.task(''develop'', function (done) {
sequence(''clean'', ''coffee'', done);
});
Pero si usted (por alguna razón) prefiere no usarlo, el método gulp.start
ayudará :
gulp.task(''develop'', [''clean''], function (done) {
gulp.on(''task_stop'', function (event) {
if (event.task === ''coffee'') {
done();
}
});
gulp.start(''coffee'');
});
Nota: si solo inicia la tarea sin escuchar el resultado, la tarea de develop
terminará antes que el coffee
, y eso puede ser confuso.
También puede eliminar el detector de eventos cuando no sea necesario.
gulp.task(''develop'', [''clean''], function (done) {
function onFinish(event) {
if (event.task === ''coffee'') {
gulp.removeListener(''task_stop'', onFinish);
done();
}
}
gulp.on(''task_stop'', onFinish);
gulp.start(''coffee'');
});
Tenga en cuenta que también task_err
evento task_err
que tal vez quiera escuchar. task_stop
se activa al finalizar con éxito, mientras que task_err
aparece cuando hay algún error.
También puede preguntarse por qué no hay documentación oficial para gulp.start()
. Esta respuesta del miembro de Gulp explica las cosas:
gulp.start
no está documentado a propósito porque puede llevar a archivos de compilación complicados y no queremos que la gente lo use
(fuente: github.com/gulpjs/gulp/issues/426#issuecomment-41208007 )