exit gulp when build is finished - gulp

I'm using gulp to minify CSS and JS files.
When I run the gulp command gulp build:website1:desktop from a terminal, it finishes successfully but it does not return to the shell prompt, I have to run Ctrl+C to return to the command prompt
Here is a what I'm using
gulp.task('build:website1:desktop', function () {
runSequence(
'website1:desktop:scripts',
'website1:desktop:css');
})
Any ideas How to exit and return to the command prompt without typing Ctrl+C every time?
Thank you in advance.

First thing is to make sure that your scripts and css tasks return a stream or a promise, so that runSequence knows when these tasks are finished. For most gulp tasks, using the return statement with gulp.src(…) will do just that:
gulp.task('website1:desktop:scripts', function() {
return gulp.src(…)
.pipe(doSomething())
.pipe(gulp.dest(…));
});
Next thing is to provide a callback for runSequence:
gulp.task('build:website1:desktop', function (callback) {
runSequence(
'website1:desktop:scripts',
'website1:desktop:css',
callback);
});
This should do the trick.

Related

Gulp Fix "gulp.run() has been deprecated" for Server Livereload

I'm new to Gulp and I found a Gulpfile.js example I wanted to use to livereload my express app's server whenever a change takes place in either my app.js file or ./public directory. Here is the Gulpfile.js code:
var gulp = require('gulp'),
spawn = require('child_process').spawn,
node;
/**
* $ gulp server
* description: Launch the server. If there's a server already running, kill it.
*/
gulp.task('server', function() {
if (node) node.kill()
node = spawn('node', ['app.js'], {stdio: 'inherit'})
node.on('close', function (code) {
if (code === 8) {
gulp.log('Error detected, waiting for changes...');
}
});
})
/**
* $ gulp default
* description: Start the development environment
*/
gulp.task('default', function() {
gulp.run('server')
gulp.watch(['./app.js', './public/'], function() {
gulp.run('server')
})
})
// clean up if an error goes unhandled.
process.on('exit', function() {
if (node) node.kill()
})
In my terminal window I keep getting the following warning:
gulp.run() has been deprecated. Use task dependencies or gulp.watch task triggering instead.
Gulp is working and it is livereloading the web application like I want it to but I'd like to fix this issue to future proof my development process, as well as get rid of this annoying warning message.
Thanks for the help!
One option would be to simply replace all occurrences of gulp.run() with gulp.start():
gulp.task('default', function() {
gulp.start('server');
gulp.watch(['./app.js', './public/'], function() {
gulp.start('server');
});
});
However calling a task explicitly using gulp.start() is not the idiomatic way of doing things in gulp (although sometimes it's necessary).
The warning message you receive already hints at the idiomatic way of solving this:
Use task dependencies or gulp.watch task triggering
Task dependencies allow you to run a task before another task. That means you can get rid of the first gulp.run().
Task triggering in gulp.watch() allows you to run a task when a file changes. That means you can get rid of the second gulp.run().
Therefore your default task ends up looking like this:
gulp.task('default', ['server'], function() {
gulp.watch(['./app.js', './public/'], ['server']);
});

Can I use Gulp 4 to run tasks in a serial fashion?

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.

Gulp Child Process hangs

I am trying to create a gulp task that updates all the assets in my project by executing a shell script. The problem is that it executes as expected and then just hangs.
'use-strict';
var gulp = require('gulp'),
gutil = require('gulp-util');
exec = require('child_process').exec;
var foreach = require('gulp-foreach');
gulp.task('update-assets', function () {
exec('./update_assets.sh', {cwd: 'assets'}, function(err, stdout, stderr) {
console.log(stdout);
console.log(stderr);
cb(err);
});
});
gulp.task('default', ['update-assets'], function() {
gulp.start('update-assets');
});
This is because of the nature of exec(). What exec() does it allows the command you give it to "take over" the current process. What you can do is instead try something like child_process.spawn . If it is a daemon process.
Take a good look at the Child_Process documentation. I think that this should help you get a good start.
Other options that may be helpful include modifying the script to throw exit codes for Gulp to recognize, or using timeouts to know when a gulp task has terminated.
UPDATE: Alternatively, you could use this, which is what I found worked for me when running a web server.
shell.exec('./update_assets.sh', {async:true} );

running gulp tasks that include shell processes synchronously

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.

gulp watch terminates immediately

I have a very minimal gulpfile as follows, with a watch task registered:
var gulp = require("gulp");
var jshint = require("gulp-jshint");
gulp.task("lint", function() {
gulp.src("app/assets/**/*.js")
.pipe(jshint())
.pipe(jshint.reporter("default"));
});
gulp.task('watch', function() {
gulp.watch("app/assets/**/*.js", ["lint"]);
});
I cannot get the watch task to run continuously. As soon as I run gulp watch, it terminates immediately.
I've cleared my npm cache, reinstalled dependencies etc, but no dice.
$ gulp watch
[gulp] Using gulpfile gulpfile.js
[gulp] Starting 'watch'...
[gulp] Finished 'watch' after 23 ms
It's not exiting, per se, it's running the task synchronously.
You need to return the stream from the lint task, otherwise gulp doesn't know when that task has completed.
gulp.task("lint", function() {
return gulp.src("./src/*.js")
^^^^^^
.pipe(jshint())
.pipe(jshint.reporter("default"));
});
Also, you might not want to use gulp.watch and a task for this sort of watch. It probably makes more sense to use the gulp-watch plugin so you can only process changed files, sort of like this:
var watch = require('gulp-watch');
gulp.task('watch', function() {
watch({glob: "app/assets/**/*.js"})
.pipe(jshint())
.pipe(jshint.reporter("default"));
});
This task will not only lint when a file changes, but also any new files that are added will be linted as well.
To add to OverZealous' answer which is correct.
gulp.watch now allows you to pass a string array as the callback so you can have two separate tasks. For example, hint:watch and 'hint'.
You can then do something like the following.
gulp.task('hint', function(event){
return gulp.src(sources.hint)
.pipe(plumber())
.pipe(hint())
.pipe(jshint.reporter("default"));
})
gulp.task('hint:watch', function(event) {
gulp.watch(sources.hint, ['hint']);
})
This is only an example though and ideally you'd define this to run on say a concatted dist file.