Chaining async jobs in gulp - gulp

I am learning some tooling and would like to use gulp for automating certain task.
My problem is I am unable to chain the tasks one after another. Below is my minimal code illustrating the issue.
The package.json has "gulp": "^4.0.2" and below is my gulpFile.js:
var gulp = require('gulp');
function showMessage(message) {
setTimeout(() => {
console.log(message);
}, 500);
}
gulp.task('task1', async () => {
showMessage("task 1 executed")
});
gulp.task('task2', async () => {
showMessage("task 2 executed")
});
gulp.task('chainExample', gulp.series('task1', 'task2'));
When calling the chainExample task, the task1 and task2 console output are executed after the task are being completed:
$ gulp chainExample
[01:11:24] Using gulpfile ..\gulpfile.js
[01:11:24] Starting 'chainExample'...
[01:11:24] Starting 'task1'...
[01:11:24] Finished 'task1' after 2.21 ms
[01:11:24] Starting 'task2'...
[01:11:24] Finished 'task2' after 819 μs
[01:11:24] Finished 'chainExample' after 7.68 ms
task 1 executed
task 2 executed
What I am trying to accomplish is to have console outputs of respective tasks within its Starting and Finished lines.
I also tried using gulp4-run-sequence with no luck and same output:
var runSequence = require('gulp4-run-sequence');
gulp.task('chainExample1', function(done) {
runSequence('task1', 'task2', function() {
done();
});
});
Please shed some lights on how I can chain the tasks in a right way. Many thanks!

Related

gulp 4 - use watch for server job instead of compiler job

If you have a task that starts and finishes, that needs to be run every time files change, that well documented here https://gulpjs.com/docs/en/getting-started/watching-files
const { watch } = require('gulp');
exports.default = function() {
// The task will be executed upon startup
watch('src/*.js', { ignoreInitial: false }, function(cb) {
// body omitted
cb();
});
};
But is there a way to use gulp watch like nodemon? Where you leave a task running, and then stop and start it whenever a file on the watchlist is changed?
--- more ---
was asked for some examples, so here are some examples that will not work
the problem is that I don't know how to set it up so that it stops the existing server whenever the watch is triggered.
---- example #1 - run server in process -----
exports.default = function() {
watch('src/*.js', { ignoreInitial: false }, function(cb) {
// this will call back but when the watch is triggered again
// it will try to start another instance
app.listen(3000, cb);
});
};
---- example #2 - run server in its own process process -----
exports.default = function() {
watch('src/*.js', { ignoreInitial: false }, function(cb) {
const proc = spawn('node', ['server.js']);
proc.stdout.pipe(process.stdout);
proc.stderr.pipe(process.stderr);
// this will never call the call back
// so never complete
cb();
});
};
Well, at least you can do like that:
% gulp someTask >/dev/null 2>&1 &
[1] _pid_
And your gulp task will run indefinitely if it's a task like watch.
But this approach is very dirty. You should use something like nodemon to achieve that.

Wait prev task before starting next tasks

I'd like to create a watcher to watch some files and compile them.
I have two tasks :
minCss
compile
I'd like to execute compile in first and wait the end before executing minCss... But it seem's not working.
My code :
var scssToCompile = [
'./public/sass/themes/adms/adms.scss',
'./public/sass/themes/arti/arti.scss',
'./public/sass/themes/avantage/avantage.scss',
'./public/sass/themes/basique/basique.scss',
'./public/sass/themes/mairie/mairie.scss',
'./public/sass/themes/vehik/vehik.scss',
'./public/sass/themes/concept/concept.scss',
'./public/sass/themes/news/news.scss',
'./public/sass/components/*.scss',
'./public/sass/_functions.scss',
'./public/sass/_settings.scss',
'./public/sass/app.scss',
'./public/sass/bottom.scss'
];
gulp.task('compile', function(){
return gulp.src(scssToCompile)
.pipe(sassGlob())
.pipe(sass({includePaths: ['./public/sass']}).on('error', function(err) {
cb(err);
}))
.pipe(gulp.dest('./public/stylesheets'));
});
gulp.task('minCss', function() {
return gulp.src('public/stylesheets/themes/**/*.css')
.pipe(minifyCss())
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('public/build/css'));
});
// my watcher
gulp.task('watch', function(){
gulp.watch(scssToCompile, ['compile', 'minCss']);
});
Results :
[15:21:36] Using gulpfile C:\xampp\htdocs\gulpfile.js
[15:21:36] Starting 'watch'...
[15:21:37] Finished 'watch' after 153 ms
[15:21:41] Starting 'compile'...
[15:21:46] Starting 'minCss'...
[15:21:46] Finished 'minCss' after 6.42 μs
[15:21:48] Finished 'compile' after 6.44 s

gulp.watch running same task multiple times when saving many files

Is there a way to configure gulp.watch to run task just once when multiple watched files change? I have my task setup like this:
var bs = require('browser-sync').create();
module.exports = function (gulp, plugins, config) {
return function watch() {
gulp.watch(
config.source.javascript,
// {debounceDelay: 500},
gulp.series('js', 'wp', bs.reload)
);
};
};
..and when I save multiple watched files at once (Save all in text editor), my gulp.series (I'm using gulp 4.0) tasks are run once for each changed file. Is there a way to change this and make gulp.watch run gulp.series tasks just once?
Thanks..
I've added a 'buffer' function like this:
var reload = false;
var delay = 500;
function brsync_reload(done) { brsync.reload(); queue_reset(done); }
function brsync_stream(done) { brsync.reload({ stream: true }); queue_reset(done); }
function queue_reload() { gulp.series(gulp.queue.concat(brsync_reload))(); }
function queue_stream() { gulp.series(gulp.queue.concat(brsync_stream))(); }
function queue_reset(done) { gulp.queue = []; reload = false; done(); }
function queue_tasks(tasks, last) {
reload = reload || last == brsync_reload;
gulp.queue = gulp.queue || [];
if (gulp.queue.length == 0)
setTimeout(reload ? queue_reload : queue_stream, delay);
gulp.queue = gulp.queue
.concat(tasks.filter(task => !gulp.queue.some(queued => queued == task)));
// console.log(gulp.queue);
}
brsync.init(CONFIG.BRSYNC);
gulp.watch(CONFIG.SRC.JAVASCRIPT, () => queue_tasks(['javascript'], brsync_reload));
gulp.watch(CONFIG.SRC.STATIC, () => queue_tasks(['static'], brsync_reload));
gulp.watch(CONFIG.SRC.STYLES, () => queue_tasks(['styles'], brsync_stream));
gulp.watch(CONFIG.SRC.TYPESCRIPT, () => queue_tasks(['typescript'], brsync_reload));
Now, when I change one file output is:
[21:40:17] Starting '<anonymous>'...
[21:40:17] Starting '<anonymous>'...
[21:40:18] Starting 'typescript'...
[21:40:21] Finished 'typescript' after 3.16 s
[21:40:21] Starting 'brsync_reload'...
[21:40:21] Finished 'brsync_reload' after 2.73 ms
...when I change 3 files (2x typescripe, 1x stylus), output is:
[21:41:19] Starting '<anonymous>'...
[21:41:19] Starting '<anonymous>'...
[21:41:19] Starting '<anonymous>'...
[21:41:19] Starting '<anonymous>'...
[21:41:19] Starting '<anonymous>'...
[21:41:19] Starting '<anonymous>'...
[21:41:20] Starting 'typescript'...
[21:41:22] Finished 'typescript' after 2.02 s
[21:41:22] Starting 'styles'...
[21:41:23] Finished 'styles' after 1.82 s
[21:41:23] Starting 'brsync_reload'...
[21:41:23] Finished 'brsync_reload' after 1.92 ms
Works nicely, only these logs of anonymous functions are annoying (;

Gulp task does not run - becomes a callback for other tasks instead

I have a task that goes like this:
var gulp = require('gulp');
gulp.task('doStuff', ['a', 'b', 'c'], function () {
console.log("success");
});
I have read the docs, and from what I understood, this is what should happen:
gulp creates a task called doStuff;
gulp runs tasks a, b and c asynchronally;
After all the three tasks above finish running, gulp runs the function I defined for doStuff.
This is what actually happens:
gulp creates a task called doStuff;
gulp runs tasks a, b and c asynchronally;
gulp indicates it has run the doStuff task with success, but does not run the function I passed as the third parameter for the gulp.task method.
I was surprised to find out that if I accept a callback in the other functions, though, that callback is my function. I.e. if I do:
var gulp = require('gulp');
gulp.task('a', function (callback) {
callback();
});
This will run my code.
I'd like my function to be executed only once, and only after all other tasks have run. What am I missing, or misinterpreting? What can I do?
By the way, this may be relevant: most of my other tasks do things like generating files, and they return such files. Like:
var gulp = require('gulp');
var rename = require('gulp-rename');
var someLogic = require('someLogicIImplementedSomewhereElse');
var path = "../../somepath";
gulp.task('foo', function() {
return gulp.src(path)
.pipe(someLogic())
.pipe(rename("renamed.js"))
.pipe(gulp.dest(path));
});
Make sure that a, b and c either return something or execute the callback.
Try the following example:
gulp.task('a', function (done) {
done();
});
gulp.task('b', function (done) {
return gulp.src('.');
});
gulp.task('c', function (done) {
done();
});
gulp.task('stuff', ['a', 'b', 'c'], function () {
console.log("success");
});
Here is the output of gulp stuff
- Starting 'a'...
- Finished 'a' after 48 μs
- Starting 'b'...
- Starting 'c'...
- Finished 'c' after 6.03 μs
- Finished 'b' after 9.14 ms
- Starting 'stuff'...
- success
- Finished 'stuff' after 38 μs

Making sense of build error while running gulp

Everytime I run my gulp task, it generates a error on first run. The error is below. When I run it again, it builds without any error.
I am confused, why does it throw an error the first time but not after that.
[08:38:08] Using gulpfile ~/Documents/Code/proj2/Gulpfile.js
[08:38:08] Starting 'stylus'...
[08:38:08] Finished 'stylus' after 7.99 ms
[08:38:08] Starting 'copyClientHTML'...
[08:38:08] Finished 'copyClientHTML' after 2.27 ms
[08:38:08] Starting 'clientLint'...
[08:38:08] Starting 'demon'...
[08:38:08] Finished 'demon' after 1.88 ms
[gulp] [nodemon] v1.2.1
[gulp] [nodemon] to restart at any time, enter `rs`
[gulp] [nodemon] watching: *.*
[gulp] [nodemon] starting `node server/js/server.js`
[08:38:08] Starting 'watch'...
[08:38:09] Finished 'watch' after 31 ms
events.js:72
throw er; // Unhandled 'error' event
^
Error: ENOENT, stat '/Users/jhans/Documents/Code/proj2/client/build/index.html'
Including Gulpfile.
/*jshint globalstrict: true*/
'use strict';
var gulp = require('gulp'),
browserify = require('gulp-browserify'),
clean = require('gulp-clean'),
jshint = require('gulp-jshint'),
stylish = require('jshint-stylish'),
stylus = require('gulp-stylus'),
del = require('del'),
nodemon = require('gulp-nodemon'),
concat = require('gulp-concat');
var paths = {
client: {
scripts: 'client/js/**/*.js',
html: 'client/views/*.html',
index: 'client/*.html',
css: 'client/css/*.styl',
conf: 'client/conf.js'
},
server: {
scripts: 'server/js/**/*.js'
}
};
// Rerun the task when a file changes
gulp.task('watch', function () {
gulp.watch(paths.client.css, ['stylus']);
gulp.watch(paths.client.scripts, ['browserify']);
gulp.watch([paths.client.html, paths.client.index], ['copyClientHTML']);
gulp.watch(paths.server.scripts, ['serverLint']);
});
gulp.task('demon', function () {
nodemon({
script: 'server/js/server.js',
ext: 'js',
env: {
'NODE_ENV': 'development'
}
})
.on('start', ['watch'])
.on('change', ['watch'])
.on('restart', function () {
console.log('restarted!');
});
});
// Default Task
gulp.task('default', ['build', 'demon']);
gulp.task('build', ['stylus', 'copyClientHTML', 'browserify']);
/********** Building CSS *********/
gulp.task('stylus', function () {
del(['client/build/css/*']);
gulp.src(paths.client.css)
.pipe(stylus())
.pipe(concat('all.css'))
.pipe(gulp.dest('client/build/css/'));
});
gulp.task('clientLint', function () {
return gulp.src([paths.client.scripts])
.pipe(jshint())
.pipe(jshint.reporter(stylish));
});
gulp.task('serverLint', function () {
return gulp.src([paths.server.scripts])
.pipe(jshint())
.pipe(jshint.reporter(stylish));
});
gulp.task('browserify',['clientLint'], function () {
del(['client/build/js/*']);
gulp.src('client/js/app.js')
.pipe(browserify({
insertGlobals: true,
debug: true
}))
.pipe(gulp.dest('client/build/js'));
});
gulp.task('copyClientHTML', function () {
del(['client/build/views/*.*']);
del(['client/build/index.html']);
gulp.src(paths.client.html)
.pipe(gulp.dest('client/build/views'));
gulp.src(paths.client.index)
.pipe(gulp.dest('client/build'));
});
Your problem might come from your copyClientHTML task (and potentially some others).
Indeed, you have to know that the del module does not run synchronously. So it might delete your files after there were created, and can explain the issue you're experiencing.
I may advice you to create a task dedicated to the cleaning of your files that you can put as dependency of some of your tasks; or better a little function where you can pass a parameter to clean specified folders.
This will ensure you that the cleaning is finished before creating the new files.