Gulp watch - execute tasks in order (synchronous)

18,001

Solution 1

Gulp starts all tasks at the 'same' time, unless you declare dependencies ( or make streams pipe one to the other ).

So for example, if you want task app_build_css to wait for tasks app_scss and app_vendor_css to complete, declare the dependencies,

gulp.task('app_scss', function(){
    return gulp.src(appScssDir + '/main.scss')
        .pipe(sass({ style: 'compressed' }).on('error', gutil.log))
        .pipe(autoprefix('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
        .pipe(gulp.dest(appBuilderDir));
});

gulp.task('app_vendor_css', function(){
    return gulp.src(appProviderCssDir + '/*.css')
        .pipe(minifyCSS({ keepSpecialComments: 0 }))
        .pipe(concat('app_vendor.css'))
        .pipe(gulp.dest(appBuilderDir));

});

gulp.task('app_build_css', ['app_scss', 'app_vendor_css'], function(){
    return gulp.src(appBuilderDir + '/*.css')
        .pipe(concat('style.css'))
        .pipe(gulp.dest(targetCssDir));
});


gulp.task('watch', function () {
    gulp.watch(appScssDir + '/**/*.scss', ['app_build_css']);
});

gulp.task('default', ['app_build_clean', 'app_build_css', 'watch']);

Check the Gulp.task() docs

Solution 2

With GULP 3 I use run-sequence package to help run tasks in sequence and not in parallel. This is how I configure my watch tasks, for example:

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

gulp.task('watch', function() {
    gulp.watch('templates/**/*.html', function(){ runSequence('templates', 'bundleJS') });
});

The above example shows a typical watch task which will hook the gulp.watch method with files which to be listened when changed, and with a callback function to run when change was detected. The runSequence function is then called (within the callback of of a certain watch) with a list of tasks to run in a synchronous manner, unlike the default way which runs tasks in parallel.

Solution 3

Gulp v4

Now that Gulp v4 has been out for nearly over a year (released at the end of 2017) it offers some great ways to sequence tasks using their library called bach.

https://github.com/gulpjs/bach

Note: I would recommend moving to Gulp v4 since v3 had some security vulnerabilities [I'm not sure if those have been patched now].

Quick Example

Gulp v4 introduces gulp.series and gulp.parallel, this allows you to create tasks and choose which run in series, parallel, or mixed as shown below.

Explanation: This will run the scss and js tasks in parallel, once those are complete it will then run the watch task because they're in series.

const defaultTasks = gulp.series(
  gulp.parallel(scss, js),
  watch
);
defaultTasks.description = 'Builds scss, and js, then watches them for changes and rebuilds upon change.';

module.exports = {
  default: defaultTasks,
  scss,
  js
}

Extended Example

Here's a stripped down example of what my gulp file may look like.

const gulpScss = require('gulp-sass');
const gulpBabel = require('gulp-babel');

const paths = {
  scss: [
    'public/stylesheets/*.scss'
  ],
  js: [
    'public/js/*.js'
  ]
};

const scss = () => {
  return gulp.src(paths.scss)
    .pipe(gulpScss)
    .pipe(gulp.dest('dist'));
}
scss.description = 'Transpiles scss files to css.';

const js = () => {
  return gulp.src(paths.js)
    .pipe(gulpBabel({
      presets: ['@babel/env']
    }))
    .pipe(gulp.dest('dist'));
}
js.description = 'Transpiles JS with babel';

const watch = () => {
  gulp.watch(paths.scss, scss);
  gulp.watch(paths.js, js);
}
watch.description = 'Watches for changes to files and runs their associated builds.';

const defaultTasks = gulp.series(
  gulp.parallel(scss, js),
  watch
);
defaultTasks.description = 'Builds scss, and js, then watches them for changes and rebuilds upon change.';

module.exports = {
  default: defaultTasks,
  scss,
  js
}

Share:
18,001

Related videos on Youtube

Lee
Author by

Lee

Updated on June 04, 2022

Comments

  • Lee
    Lee almost 2 years

    I have a series of tasks to be run from a watcher but I can get them to fire in order:

    Here is the gulp tasks and watcher.

    gulp.task('app_scss', function(){
        return gulp.src(appScssDir + '/main.scss')
            .pipe(sass({ style: 'compressed' }).on('error', gutil.log))
            .pipe(autoprefix('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
            .pipe(gulp.dest(appBuilderDir));
    });
    
    gulp.task('app_vendor_css', function(){
        return gulp.src(appProviderCssDir + '/*.css')
            .pipe(minifyCSS({ keepSpecialComments: 0 }))
            .pipe(concat('app_vendor.css'))
            .pipe(gulp.dest(appBuilderDir));
    
    });
    
    gulp.task('app_build_css', function(){
        return gulp.src(appBuilderDir + '/*.css')
            .pipe(concat('style.css'))
            .pipe(gulp.dest(targetCssDir));
    });
    
    
    gulp.task('watch', function () {
        gulp.watch(appScssDir + '/**/*.scss', ['app_scss', 'app_build_css']);
    });
    
    gulp.task('default', ['app_build_clean', 'app_scss', 'app_vendor_css', 'app_build_css', 'watch']);
    

    So when I update a scss file it should compile them create a single css file. Then the build task concats the file with the vendor files. But every time I save a file its always one step behind. See the video as an example: http://screencast.com/t/065gfTrY

    I have renamed the tasks, changed the order in the watch callback etc.

    Am I making a obvious mistake?

  • Lee
    Lee about 10 years
    Excellent. Pulling my hair out on that one. TY
  • AntouanK
    AntouanK about 10 years
    Yeah, me too, until I read the documentation. Using the callback and promises are also very interesting, in that you can create more complex scenarios, if your project build needs them.
  • benzkji
    benzkji about 7 years
    simple and efficient. also works for example when both tasks are in the default task, without further fiddling. if your scenario is not too complex, I prefer this answer.