Basic question but i just cannot find answer yet.
var gulp = require('gulp');
gulp.task('one', function(cb) {
// do stuff -- async or otherwise
cb(err);
});
gulp.task('two', function(cb) {
// do something
cb(err)
});
gulp.task('three', function(cb) {
// do something
cb(err)
});
The Q is: does task 2 only runs when task 1 finishes, task 3 only runs when task 2 finishes ?
With just this setup, only one task will be executed at all, e.g. task two if you invoke gulp two.
You can create composite tasks with the help of the functions series(...) and parallel(...) provided by Gulp. The new task will run the tasks passed to the function either in sequence or in parallel. Calls to the functions can be nested to create more complex scenarios.
Related
I have problems with Gulp Watch when it only has to process the files that have been modified
When I start, Gulp performs the tasks correctly, but when I make a change Gulp watch performs all the tasks again instead of just those that were changed. I do not know what the problem could be, could you help me?
// Watch Task: watch SCSS and JS files for changes
// If any change, run scss and js tasks simultaneously
function watchTask() {
watch([files.htmlPath, files.scssPath, files.mincssPath, files.cssPath, files.minjsPath, files.jsPath, files.imgPath],
parallel(htmlTask, siteTask, series(scssTask, cleanTask, concatCSS), series(jsminTask, jsTask), imgTask));
}
// Export the default Gulp task so it can be run
// Runs the scss and js tasks simultaneously
// then runs cacheBust, then watch task
exports.default = series(
parallel(htmlTask, siteTask, series(scssTask, cleanTask, concatCSS), series(jsminTask, jsTask), imgTask),
cacheBustTask,
watchTask
);
To achieve your goal you should create separate watch functions and run them in parallel.
Some thing like that:
exports.watch = gulp.parallel(watch_html, watch_scss,...);
function watch_html() {
return gulp.watch(files.htmlPath, htmlTask);
}
function watch_scss(){
return gulp.watch(files.scssPath, series(scssTask, cleanTask, concatCSS));
}
I have a large build that is composed of multiple sub-projects that are all built from a central set of shared gulp scripts.
Say I want to do this (there are other modules that define the actual tasks for the sub-projects):
var apps = [...]; //list of configuration objects for sub-projects in question
function builds() {
var buildNames = apps.map(function (app) {
return "release-build-" + app.name;
});
return gulp.parallel(buildNames);
}
function tests() {
var testNames = apps.map(function (app) {
return "test-" + app.name;
});
return gulp.series(testNames);
}
gulp.task("test", tests);
gulp.task("release-build", gulp.series(tests, builds));
In gulp 3 I do the following (the code for the release-build task follows the same pattern as test):
var runSequence = require("run-sequence").use(gulp);
gulp.task("test", function (callback) {
// Get the test tasks of all children
var tasks = apps.map(function(app) {
return "test-" + app.name;
});
tasks.push(callback);
//run tasks sequentially
return runSequence.apply(null, tasks);
});
However when I try to run the new gulp 4 version I get the dreaded:
The following tasks did not complete 'test'
Did you forget to signal async completion?
How can I build my tasks names and pass them to gulp.series() or gulp.parallel() in gulp 4 like I did with run-sequence?
Your builds and tests functions generate gulp.parallel() and gulp.series() task compositions. What you want to do is assign those generated task compositions as your test and release-build tasks.
What you are currently doing is to assign the builds and tests functions themselves as your tasks instead of their return values.
You need to actually invoke the builds and tests functions. So instead of this:
gulp.task("test", tests);
gulp.task("release-build", gulp.series(tests, builds));
You need to do this:
gulp.task("test", tests());
gulp.task("release-build", gulp.series(tests(), builds()));
My code currently uses run-sequence to run a series of tasks. From what I was told I can now do this using native Gulp 4. Can someone confirm if this is possible and if so advise how I could do this.
var runSequence = require('run-sequence');
gulp.task('make-prod-ex1', function () {
makeAppHtml('app/**/*ex1', function () {
runSequence(
'makeTemplate',
'clean-css',
'make-css-files',
'make-css-bundle',
'rename-css-bundle',
'clean-js',
'make-js-bundle',
'rename-js-bundle',
'rename-index',
function () {
console.log("Completed");
});
});
});
In Gulp 4.0 gulp.series() and gulp.parallel() completely replace the task dependency mechanism that was used in Gulp 3.x. That means you can't write things like gulp.task('task1', ['task2']) anymore.
Instead of telling Gulp which tasks depend on each other and letting Gulp decide the execution order based on the dependency graph, you now have to explicitly define the execution order by composing gulp.series() and gulp.parallel() calls. Both can accept task names as well as functions and return functions themselves:
gulp.task('make-prod-ex1', gulp.series(
function(done) {
makeAppHtml('app/**/*ex1', done);
},
'makeTemplate',
'clean-css',
'make-css-files',
'make-css-bundle',
'rename-css-bundle',
'clean-js',
'make-js-bundle',
'rename-js-bundle',
'rename-index',
function (done) {
console.log("Completed");
done();
}));
As usual you have to make sure to signal async termination by either calling a done callback or returning streams in your tasks/functions. From personal experience it seems that Gulp 4.0 is a lot more quick to complain about this than Gulp 3.x was.
I am new to gulp.
I have written two task that need to be performed. When I run them separately, they work fine. But when I combine them, the "replace" does not work.
gulp.task('bundle-source', function () {
return bundler.bundle(config);
});
gulp.task('bundle-config', function(){
return gulp.src(['config.js'])
.pipe(replace('src/*', 'dist/*'))
.pipe(gulp.dest(''));
});
gulp.task('bundle', ['bundle-config', 'bundle-source']);
I think the issue is that they both manipulate config.js. I think the second task when it saves to disk overwrites the change the first one made. The second task is about 30 seconds.
Gulp tasks are run in parallel by default. So if your tasks are working on the same files, they might step on each others' toes indeed.
You can use gulp's tasks dependencies to have them run one after the other. So if bundle-config should be run before bundle-source :
gulp.task('bundle-source', ['bundle-config'], function () {
return bundler.bundle(config);
});
You can also use a package like run-sequence if you need them to run one after the other :
var seq = require('run-sequence');
gulp.task('bundle', function(cb) {
return seq('bundle-config', 'bundle-source', cb);
});
Finally, You could use gulp 4, which has a built-in mechanism to run tasks in series.
I am trying to use gulp as an installer for complex system that involves creating folder, copying files around and runnin compliation scripts.
Presently I have the following gulp tasks:
// Some tasks skipped that set sessionFolder
gulp.task('default', function () {
// Main
runSequence('prepare_comedi', 'compile_comedi');
});
gulp.task('prepare_comedi', function () {
// Copies comedi files into build folder
gulp.src(['../comedi/**/*']).pipe(gulp.dest(sessionFolder));
});
gulp.task('compile_comedi', function () {
var logfile=this.currentTask.name+'.log';
gutil.log(gutil.colors.green(this.currentTask.name), ": building and installing COMEDI, logging to "+logfile);
var cmd= new run.Command('{ ./autogen.sh; ./configure; make; make install; depmod -a ; make dev;} > ../'+logfile+ ' 2>&1', {cwd:sessionFolder+'/comedi', verbosity:3});
cmd.exec();
});
When I run gulp, it becomes obvious that the processes start in background and gulp task finishes immediately. The first task above should copy source files, and second one compile them. In practice, second task hits the error, as the first task is not ready with copying when second task (almost immediately) starts.
If I run second task alone, previosuly having all files from first task copied, it works ok, but I have output like this:
[19:52:47] Starting 'compile_comedi'...
[19:52:47] compile_comedi : building and installing COMEDI, logging to compile_comedi.log
$ { ./autogen.sh; ./configure; make; make install; depmod -a ; make dev;} > ../compile_comedi.log 2>&1
[19:52:47] Finished 'compile_comedi' after 6.68 ms
So it takes 6.68 millisec to leave the task, while I want gulp to leave it only after all compilations specified in the task are finished. I then would run another compile process that uses built binaries from this step as a dependency.
How I can run external commands in such a way, that next gulp task starts only after first task complete execution of an external process?
You should make sure that the task prepare_comedi is finalized prior to start compile_comedi. In order to do so, since you're using regular streams on the prepare task, simply return the stream:
gulp.task('prepare_comedi', function () {
// !!! returns the stream. Gulp will not consider the task as done
// until the stream ends.
return gulp.src(['../comedi/**/*']).pipe(gulp.dest(sessionFolder));
});
Since these tasks are interdependent and require certain order, you might also want to consider refactoring your code to actually create two methods and call them normally. Take a look at this note.
Update
Addressing your question in the comment below, if you want to hold a task until some asynchronous job has been completed, you have pretty much three choices:
return a stream (case above)
returning a promise and fulfilling it when you're done (using Q in this example):
var Q = require('Q');
gulp.task('asyncWithPromise', function() {
var deferred = Q.defer();
// anything asynchronous
setTimeout(function() {
Q.resolve('nice');
}, 5000);
return deferred.promise;
});
Receiving a callback function and calling it
gulp.task('asyncWithPromise', function(done) {
setTimeout(function() {
done();
}, 5000);
});
These approaches are in the docs.