Gulp watch - execute tasks in order (synchronous)
Asked Answered
E

4

17

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?

Envelop answered 27/2, 2014 at 23:7 Comment(0)
E
20

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

Eponymous answered 28/2, 2014 at 0:9 Comment(3)
Excellent. Pulling my hair out on that one. TYEnvelop
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.Eponymous
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.Typecast
C
21

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.

Cleopatracleopatre answered 19/1, 2016 at 9:40 Comment(4)
Excellent, but better is: gulp.watch('templates/**/*.html', () => runSequence('templates', 'bundleJS'))On
gulp-watch is not needed in this example. var watch is never used. gulp.watch is available on var gulp. gulp-watch is like gulp.watch but boasts several advantages over gulp.watchHistorical
This plugin is a temporary fix. The author specifies that in the docs. In gulp 4 the tasks will be executed sequentially as specified e.g gulp.watch([bases.assets + paths.sass], ['sass','styles']); sass tasks will be executed then styles taskIvan
@CengkuruMichael - yes it's quite known for years now. this "temporary" fix has become the standard... Gulp 4 seems will never go public since there are zero updates from the team in their twitter page and no progress on the branch at all on githubCleopatracleopatre
E
20

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

Eponymous answered 28/2, 2014 at 0:9 Comment(3)
Excellent. Pulling my hair out on that one. TYEnvelop
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.Eponymous
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.Typecast
F
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
}

Foucquet answered 15/2, 2019 at 2:37 Comment(0)
D
0

I found useful to defines a "series" task with this syntax

gulp.task('jsLib', gulp.series(
    function copiaLibJs () {
        return gulp
            .src(paths.lib.files)
            .pipe(rename(function(path) {
                path.dirname = path.dirname.replace(/\/dist/, '').replace(/\\dist/, '');
            }))
            .pipe(gulp.dest(paths.lib.dest));
    },
    function fontAwesomeCss(){
        return gulp.src('node_modules/font-awesome/css/**').pipe(gulp.dest(paths.css.dest));
    },
    function fontAwesomeFonts(){
        return gulp.src('node_modules/font-awesome/fonts/**').pipe(gulp.dest(paths.font.dest));
    }

));
Dagenham answered 16/4, 2022 at 16:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.