Gulp watch runs only once - gulp

I'm trying to finish my gulpfile.js but I'm running into a problem with "gulp watch". When I set my watcher to run, it detects changes and run the assigned task, but only once. The next changes on the files don't trigger the tasks anymore. I don't know why, but my watcher is working just once.
I believe the watcher is not realizing the tasks it triggered are finished. Or, maybe it's something to deal with the lazy loading or run-sequence plugins I'm using...
var
gulp = require('gulp'),
plugins = require('gulp-load-plugins')({
DEBUG: true
});
plugins.runSequence = require('run-sequence');
gulp.task('watch',function(){
gulp.watch('public/**/*.+(css|js)',['buildEspecifico']);
});
gulp.task('buildEspecifico',function(callback){
return plugins.runSequence(
['deletarMainMin'],
['agruparJS','agruparCSS']
);
});
'deletarMainMin','agruparJS','agruparCSS' are other tasks defined in the same gulpfile.
Thanks in advance!
Cheers,
Fabio.

I believe the watcher is not realizing the tasks it triggered are finished.
Yes, that is exactly it. In your buildEspecifico task you accept a callback. That means gulp will not consider your buildEspecifico task to have finished unless you invoke that callback.
Since you don't invoke callback the buildEspecifico task never actually finishes once it runs. And because your buildEspecifico task is technically still running gulp doesn't start the task again when a file changes.
The solution is to pass callback to runSequence. It will invoke the callback when all of your tasks in the sequence have finished.
gulp.task('buildEspecifico',function(callback){
return plugins.runSequence(
['deletarMainMin'],
['agruparJS','agruparCSS'],
callback
);
});
Alternatively you can also just leave out the callback altogether:
gulp.task('buildEspecifico',function(){
return plugins.runSequence(
['deletarMainMin'],
['agruparJS','agruparCSS']
);
});
Obviously you have to make sure that the tasks deletarMainMin, agruparJS, agruparCSS themselves finish, so either call or leave out the callback in those tasks too.

Related

Gulp Task does not include subfolders

I'm trying to set up a Gulp task for eslint (System: OS Windows 10). But it seems that the src is not being evaluated correctly:
gulp.task('lint-app-basic-an', function() {
gulp.src('src/main/webapp/app-basic-an/**/*.js')
.pipe(eslint({
configFile: '.eslintrc.js'
}))
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});
There are several subfolders underneath src/main/webapp/app-basic-an, e.g.
src/main/webapp/app-basic-an/components/page-header/page-header.component.js
If I create a lint error in said JS-File, it is ignored by the linter. If I specify the path 1 level more in the tasks .src-function like
gulp.src('src/main/webapp/app-basic-an/components/**/*.js')
It suddenly works, which makes no sense to me, I thought "**/" meant zero or more subdirectories?
Gulp executes its tasks in an asynchronous manner. For gulp to be able to know that some task has finished, the tasks needs to do one of the following:
return stream (e.g. the one created by gulp.src) on which gulp can listen for end event,
return q promise or
call callback function passed as task function argument
If the task does not accept arguments and does not return promise or stream, gulp considers that task synchronous (i.e. it is finished once the function call returns). Once all tasks are finished, the execution stops... hence if you have some async processing, it will never finish (or worse - it might end at a random point).

How to trigger dependant task after gulp watch

I've been trying to figure out how to trigger a dependant task after a task which uses gulp-watch. I guess I'm doing something bad here. So, what I want to do is to transpile whole project (+ watch the changes) and after that's done I want to trigger a bundling task that is dependant on this one. Since task of transpiling has watching included, I can't put it as dependant task, but I need a way to know when whole transpiling has been done, to do the initial bundling and on each change I want to do the bundle again.
How to do this?
This is how the transpilation task looks like:
gulp.task('babel', () => {
return gulp.src(babelSrc)
.pipe(watch(babelSrc, () => console.log('watch'))
.pipe(babel({...}))
.pipe(gulp.dest('build'));
});
Callback passed to watch will console log watch everytime a file has been transpiled, which I can use only after to trigger bundling task only after initial transpilation of the whole project has been done.
what I want to do is to transpile whole project [...] and after that's done I want to trigger a bundling task
That's not possible the way you're doing it now. When you .pipe() the gulp-watch plugin it prevents the stream from emitting the 'end' and 'finish' events. So there's no way to know when the initial babel compilation has finished.
You need to separate the initial compilation from the watch.
That way you can listen for the 'end' event and trigger your dependent task from there.
gulp.task('dependend-task', () => {
...
});
function babelStream(stream) {
return stream
.pipe(babel({...}))
.pipe(gulp.dest('build'))
.on('end', () => gulp.start('dependend-task'));
}
gulp.task('babel', () => {
watch(babelSrc, {ignoreIntial:true, read:false}, function(file) {
return babelStream(gulp.src(file.path));
});
return babelStream(gulp.src(babelSrc));
});

Wait for completion in Gulp tasks

I've specified some Gulp tasks in a gulpSequence like this:
gulp.task('default', function(done){
gulpSequence(
'private:clean',
'private:copy-app-package-file',
'private:copy-app-main-file',
'private:copy-libs',
'private:copy-app-files',
'private:copy-css-files',
'private:build-html',
'private:package-app',
done);
});
I thought that they should run one after another. The build-html tasks needs the libs, app-files and css-files, because they get included within one html file.
But if I run the default task, the build-html task is missing some files. For example the task can only inject 10 files in the html file but there are 16 files.
Is there another way to specify dependent tasks. I thought the gulpSequence will handle this.
You're on the right lines, but the npm package you are trying to use is depreciated. Might be worth considering checking out run-sequence (https://www.npmjs.com/package/run-sequence) which waits for a previous task to complete before starting.
So in your instance, this would become
gulp.task('default', function( cb ) {
$.runSequence(
'private:clean',
'private:copy-app-package-file',
'private:copy-app-main-file',
'private:copy-libs',
'private:copy-app-files',
'private:copy-css-files',
'private:build-html',
'private:package-app',
cb
)
});
You specified that all tasks should run in sequence with no parallelism at all. A new task starts as soon as a former task shows completion.
Probably you have some issues in a task before the build-html task. Do they handle the completion (done() callback) correctly? In most cases I saw there was some async action triggered and the callback was called before the async task finished. So the sequence continues before the task is really over...

gulp.watch only runs once when passed a run-sequence task

I have a gulpfile, it uses run sequence and gulp.watch().
Here is an example task that uses run sequence.
gulp.task('rebuild', function (callback) {
runSequence('clean',
'lint',
['process-js', 'process-styles', 'move-fonts', 'move-static-content']);
});
When I make a change to a file, the watch task will run the task I specified exactly once. In this case, the task that should be executed is "run", which is the same as the default task except it doesn't run the dev server and watch task again. Nothing happens when I make further edits, whether in the same file or a different one.
If I pass gulp.watch a plain gulp task (without run sequence), for example the clean task, then the watch will run the clean task every time.
I'm sure I'm doing something wrong, but I don't understand what. I think something might be silently erroring and disconnecting the stream, but I can't figure out how to debug this.
You aren't passing the callback into run-sequence, therefore the task never completes. - OverZealous
So the run sequence task needs to look like this:
gulp.task('rebuild', function (callback) {
runSequence('clean',
'lint',
['process-js', 'process-styles', 'move-fonts', 'move-static-content'],
callback);
});

Gulp task order

I'm having some trouble with a couple of gulp tasks. i've tried everything and followed the documentation but nothing seems to work. Hoping someone can help.
What i'm trying to do is have sass minification happen, then rsync the result to a local vagrant folder (NOT a remote server), then reload browser sync.
The problem i am having is that I'm fighting the fact that gulp wants to run all the tasks together. I need them to happen one after the other. All the tasks work on their own, i am just having trouble making them run sequentially. I've tried callbacks and playing with dependency but i'm obviously missing something.
My setup is complicated, all my tasks are in separate js files but i've tried to combine what i have into this single github gist so people can help. Thanks for any assistance.
https://gist.github.com/CodeStalker/9661725dcaf105d2ed6c
The only way I have got this to work is to pipe rsync onto the end of the sass magnification, and wrap it in gulp-if using a server: true variable so it only does the rsync if it knows its running on a VM. Not ideal.
This is a common issue people run into with Gulp, especially when coming from Grunt. Gulp is async to the max, it always wants to do as many things as it can all at the same time.
The first step to getting tasks to run sequentially is to let gulp know when your task ends, this can be done a couple different ways.
1) Return a stream, gulp will wait for the stream's "end" event as the trigger for that task being done. Example:
gulp.task( "stream-task", function(){
return gulp.src( srcGlob )
.pipe(sass())
.pipe(compressCSS())
.pipe(gulp.dest( destGlob ));
});
2) Return a Promise, gulp will wait for the promise to enter a resolved state before signaling the task as done. Example: (not perfect just to get the point across)
gulp.task( "promise-task", function() {
return new Promise(function(resolve, reject){
fs.readFile( "filename", function( err, data ){
if( err ){ return reject(err); }
return resolve( data );
});
});
});
3) Call the task callback, if the function doesn't return anything but the function signature takes an argument, that argument will be a callback function you can call to signal the task as done. Example:
gulp.task( "cb-task", function( done ){
fs.readFile( "filename", function( err, data ){
// do stuff, call done...
done();
});
});
Most often you are going to be returning a stream like example 1, which is what a typical gulp task looks like. Options 2 and 3 are more for when you are doing something that isn't really a traditional stream based gulp task.
The next thing is setting the "dependency" of one task for another. The gulp docs show this as the way you do that:
gulp.task( "some-task-with-deps", [ "array-of-dep", "task-names" ], function(){ /* task body */ });
Now I don't know the current status but there were some issues with these dependency tasks not running in the proper order. This was originally caused by a problem with one of gulp's dependencies (orchestrator I believe). One kind gentleman out there in NPM land made a nice little package to be used in the interim while the bugs were being worked out. I started using it to order my tasks and haven't looked back.
https://www.npmjs.com/package/run-sequence
The documentation is good so I won't go into a lot of detail here. Basically run-sequence lets explicitly order your gulp tasks, just remember it doesn't work if you don't implement one of the three options above for each of your tasks.
Looking at your gist adding a couple missing return statements in your tasks may just do the trick, but as an example this is what my "dev" task looks like for my project at work...
gulp.task( "dev", function( done ){
runSequence(
"build:dev",
"build:tests",
"server:dev",
[
"less:watch",
"jscs:watch",
"lint:watch",
"traceur:watch"
],
"jscs:dev",
"lint:dev",
"tdd",
done // <-- thats the callback method to gulp let know when this task ends
);
});
Also for reference my "build:dev" task is another use of run-sequence
gulp.task( "build:dev", function( done ){
runSequence(
"clean:dev",
[
"less:dev",
"symlink:dev",
"vendor:dev",
"traceur:dev"
],
done // <-- thats the callback method to let know when this task ends
);
});
If the tasks need to be run in order the task name gets added as its own argument to runSequence if they don't conflict send them in as an array to have the tasks run at the same time and speed up your build process.
One thing to note about watch tasks! Typically watch tasks run indefinitely so trying to return the "infinite" stream from them may make gulp think that the task never ends. In that case I'll use the callback method to make gulp think the task is done even if it is still running, something like...
gulp.task( "watch-stuff", function( done ){
gulp.watch( watchGlob )
.on( "change", function( event ){ /* process file */ });
done();
});
For more on watch tasks and how I do incremental builds check out an answer I wrote the other day, Incremental gulp less build
Here you go, I believe it should work now. If not let me know, I might have made a typo.
Your gist fixed
I think you are hitting (i don't have enough reputation points to post link, google issues #96) which is fixed in 4.x which isn't out yet :-). That said, check this hack out: My post about Gulp v3.x bug