44

On the gulp page there is the following example:

gulp.task('clean', function(cb) {
  // You can use multiple globbing patterns as you would with `gulp.src`
  del(['build'], cb);
});

gulp.task('scripts', ['clean'], function() {
  // Minify and copy all JavaScript (except vendor scripts)
  return gulp.src(paths.scripts)
    .pipe(coffee())
    .pipe(uglify())
    .pipe(concat('all.min.js'))
    .pipe(gulp.dest('build/js'));
});

// Copy all static images
gulp.task('images', ['clean'], function() {
 return gulp.src(paths.images)
    // Pass in options to the task
    .pipe(imagemin({optimizationLevel: 5}))
    .pipe(gulp.dest('build/img'));
});

// the task when a file changes
gulp.task('watch', function() {
  gulp.watch(paths.scripts, ['scripts']);
  gulp.watch(paths.images, ['images']);
});

// The default task (called when you run `gulp` from cli)
gulp.task('default', ['watch', 'scripts', 'images']);

This works quite well. But there is one big problem with the watch task. If I change an image, the watch task detect it and runs the images task. This also has a dependency (gulp.task('images', **['clean']**, function() {) on the clean task, so this runs also. But than my script files are missing because the scripts task did not start again and the clean task deleted all files.

How can I just run the clean task on the first startup and keep the dependencies?

punkrockbuddyholly
  • 9,675
  • 7
  • 36
  • 69
Jan Hommes
  • 5,122
  • 4
  • 33
  • 45

6 Answers6

41

You can make separate tasks to be triggered by watch:

gulp.task('clean', function(cb) {
  // You can use multiple globbing patterns as you would with `gulp.src`
  del(['build'], cb);
});

var scripts = function() {
  // Minify and copy all JavaScript (except vendor scripts)
  return gulp.src(paths.scripts)
    .pipe(coffee())
    .pipe(uglify())
    .pipe(concat('all.min.js'))
    .pipe(gulp.dest('build/js'));
};
gulp.task('scripts', ['clean'], scripts);
gulp.task('scripts-watch', scripts);

// Copy all static images
var images = function() {
 return gulp.src(paths.images)
    // Pass in options to the task
    .pipe(imagemin({optimizationLevel: 5}))
    .pipe(gulp.dest('build/img'));
};
gulp.task('images', ['clean'], images);
gulp.task('images-watch', images);

// the task when a file changes
gulp.task('watch', function() {
  gulp.watch(paths.scripts, ['scripts-watch']);
  gulp.watch(paths.images, ['images-watch']);
});

// The default task (called when you run `gulp` from cli)
gulp.task('default', ['watch', 'scripts', 'images']);
Ben
  • 10,056
  • 5
  • 41
  • 42
  • works, but kind of difficult. Luckily the gulp team is working on a new [task solution](https://github.com/gulpjs/gulp/issues/355). – Jan Hommes Jun 29 '14 at 09:59
  • I'm having trouble with cleaning things first, maybe having individual clean tasks would be better than breaking up the watch task. – blues_driven Feb 25 '15 at 12:10
  • 3
    @blues_driven Try `return`ing the `del`-call instead of passing the `cb`-callback to it... As here: https://github.com/gulpjs/gulp/blob/a2c9e695ecf3600f21fa731e705fd1a0503632d9/docs/recipes/delete-files-folder.md – yckart Jan 20 '16 at 01:17
  • 1
    Use `del.sync` otherwise you'll be adding files while some are still being deleted. – Dave May 24 '16 at 13:50
  • @yckart is right - "del" 2.0 API has changed to use promises. – Nick Pineda Jun 06 '16 at 21:27
  • 'scripts' depends on 'clean' (1st). And 'images' depends on 'clean' (2nd). But couldn't the 1st 'clean' finish, so the 'scripts' begin piping, just as the 2nd 'clean' begins (i.e. the 'clean' from 'images' begins deleting the scripts written by 'scripts' )? I understand that **returning `del(...)`** will prevent 'scripts' from executing before **its own** 'clean', but what will prevent 'scripts' write from executing before **images'** 'clean'? – Nate Anderson Mar 30 '17 at 17:57
  • That's it! Solved to me! – Francis Rodrigues May 26 '17 at 14:55
19

Use del.sync. It completes the del and then returns from the task

gulp.task('clean', function () {
    return $.del.sync([path.join(conf.paths.dist, '/**/*')]);
});

and be sure clean is the first task in a list of tasks. For example,

gulp.task('build', ['clean', 'inject', 'partials'], function ()  {
    //....
}

@Ben i liked the way you have separated clean:css clean:js tasks. That's a great tip

SonKrishna
  • 189
  • 1
  • 4
5

Just use the module directly as gulp.src is costly. Make sure you use the sync() method otherwise you may have conflicts.

gulp.task('clean', function () {
    del.sync(['./build/**']);
});

The other way to do it if you want to use the gulp pipes: https://github.com/gulpjs/gulp/blob/master/docs/recipes/delete-files-folder.md

var del = require('del');
var vinylPaths = require('vinyl-paths');

gulp.task('clean:tmp', function () {
  return gulp.src('tmp/*')
    .pipe(vinylPaths(del))
    .pipe(stripDebug())
    .pipe(gulp.dest('dist'));
});
magiccrafter
  • 5,175
  • 1
  • 56
  • 50
3

I had an issue with the callback method. The callback was running before the del operation had completed, causing errors. The fix was returning the del result to the caller as below:

// Clean
gulp.task('clean', function() {
    return del(['public/css', 'public/js', 'public/templates'])
});

// Build task
gulp.task('build', ['clean'], function() {
    console.log('building.....');
    gulp.start('styles', 'scripts', 'templates');
});
2

I found this problem. I just clean my target files in my task. like this:

gulp.task('img', function() {
    //clean target before all task
    del(['build/img/*']);
    gulp.src(paths.images)
        .pipe(gulp.dest('build/img'));
});

just one line to solve it. Hope this could help you.

famousgarkin
  • 13,687
  • 5
  • 58
  • 74
stackFish
  • 597
  • 4
  • 12
  • 13
    Pay attention to the concurrency: del and the inner gulp flow will start at the same time. – Ghidello Nov 21 '14 at 08:05
  • 4
    you should use `del.sync(patterns, [options])` or put the `gulp.src` in a callback. watch https://www.npmjs.com/package/del#del-sync-patterns-options for more details – Amit Choukroun Aug 07 '15 at 11:06
2

for the default task I would suggest using 'run-sequence' to run a sequence of gulp tasks in a specified order, check it out here: https://www.npmjs.com/package/run-sequence
then I would use the 'watch' task as I normally do.

for the images task I would add caching since it's an heavy task, check it out here: https://www.npmjs.com/package/gulp-cache

combining it all together will look something like the following:

var gulp = require('gulp');
var runSequence = require('run-sequence');
var del = require('del');
var cache = require('gulp-cache');

// Clean build folder function:
function cleanBuildFn() {
    return del.sync(paths.build);
}

// Build function:
function buildFn(cb) {
    runSequence(
        'clean:build', // run synchronously first
        ['scripts, 'images'], // then run rest asynchronously
        'watch',
        cb
    );
}

// Scripts function:
function scriptsFn() {
  return gulp.src(paths.scripts)
    .pipe(coffee())
    .pipe(uglify())
    .pipe(concat('all.min.js'))
    .pipe(gulp.dest('build/js'));
}

// Images function with caching added:
function imagesFn() {
    gulp.src(paths.source + '/images/**/*.+(png|jpg|gif|svg)')
    .pipe(cache(imagemin({optimizationLevel: 5})))
    .pipe(gulp.dest(paths.build + '/images'));
}

// Clean tasks:
gulp.task('clean:build', cleanBuildFn);

// Scripts task:
gulp.task('scripts', scriptsFn);

// Images task:
gulp.task('images', imagesFn);

// Watch for changes on files:
gulp.task('watch', function() {
    gulp.watch(paths.source + '/images/**/*.+(png|jpg|gif|svg)', ['images']);
    gulp.watch(paths.source + '/scripts/**/*.js', ['scripts']);
});

// Default task:
gulp.task('default', buildFn);
Ilia luk
  • 2,065
  • 2
  • 16
  • 18