Search code examples
javascriptnode.jsgulpgulp-watch

Refactored watch task using gulp v4 doesn't work


I'm refactoring my gulpfile now I'm using gulp v4 and am having an issue with gulp watch not running my stylesCompileIncremental function. Any help or pointers would be much appreciated.

My refactoring includes:

  • Switching to using functions instead of gulp.task
  • Using series and parallel as per the docs
  • Exporting public tasks at the bottom of my gulpfile ie exports.stylesWatch = stylesWatch;
  • Adding callbacks in functions to tell Gulp the function is complete

The code for the affected tasks is as follows (directory paths are stored in package.json file hence pathConfig.ui... values):

// Compile only particular Sass file that has import of changed file
function stylesCompileIncremental(cb) {
    sassCompile({
        source: getResultedFilesList(changedFilePath),
        dest: pathConfig.ui.core.sass.dest,
        alsoSearchIn: [pathConfig.ui.lib.resources]
    });
    cb();
}

// Compile all Sass files and watch for changes
function stylesWatch(cb) {
    createImportsGraph();
    var watcher = gulp.watch(pathConfig.ui.core.sass.src + '**/*.scss', gulp.parallel(devServReloadStyles));
    watcher.on('change', function(event) {
        changedFilePath = event;
    });
    cb();
}

// reload css separated into own function. No callback needed as returning event stream
function reloadCss() {
    return gulp.src(generateFilePath)
        .pipe($.connect.reload()); // css only reload
}

function devServReloadStyles(cb) {
    gulp.series(stylesCompileIncremental, reloadCss);
    cb();
}

When I run gulp stylesWatch using my refactored code I get the below output (notice the stylesCompileIncremental task is not run):

Refactored output

So my watch tasking is successfully running but there's something wrong when the devServReloadStyles is run for the stylesCompileIncremental function to not kick in.

The original code before refactoring (when using gulp v3) is below:

// Compile only particular Sass file that has import of changed file
gulp.task('styles:compile:incremental', () => {
    return sassCompile({
        source: getResultedFilesList(changedFilePath),
        dest: pathConfig.ui.core.sass.dest,
        alsoSearchIn: [pathConfig.ui.lib.resources]
    });
});

// Compile all Sass files and watch for changes
gulp.task('styles:watch', () => {
    createImportsGraph();
    gulp.watch(
        pathConfig.ui.core.sass.src + '**/*.scss',
        ['devServ:reload:styles']
    ).on('change', event => changedFilePath = event.path);
});

// Reload the CSS links right after 'styles:compile:incremental' task is returned
gulp.task('devServ:reload:styles', ['styles:compile:incremental'], () => {
    return gulp.src(generateFilePath) // css only reload
        .pipe($.connect.reload());
});

The original task output when running styles:watch is this:

Original output

And this is the sassCompile variable used inside stylesCompileIncremental which I've currently not changed in anyway.

    /**
* Configurable Sass compilation
* @param {Object} config
*/
const sassCompile = config => {
    const sass = require('gulp-sass');
    const postcss = require('gulp-postcss');
    const autoprefixer = require('autoprefixer');

    const postProcessors = [
        autoprefixer({
            flexbox: 'no-2009'
        })
    ];

    return gulp.src(config.source)
        .pipe($.sourcemaps.init({
            loadMaps: true,
            largeFile: true
        }))
        .pipe(sass({
            includePaths: config.alsoSearchIn,
            sourceMap: false,
            outputStyle: 'compressed',
            indentType: 'tab',
            indentWidth: '1',
            linefeed: 'lf',
            precision: 10,
            errLogToConsole: true
        }))
        .on('error', function (error) {
            $.util.log('\x07');
            $.util.log(error.message);
            this.emit('end');
        })
        .pipe(postcss(postProcessors))
        .pipe($.sourcemaps.write('.'))
        .pipe(gulp.dest(config.dest));
};

UPDATE

This is due to an issue with my devServReloadStyles function, although I'm still unsure why. If I change my stylesWatch function to use the original devServ:reload:styles task stylesCompileIncremental gets run.

// Compile all Sass files and watch for changes
function stylesWatch(cb) {
    createImportsGraph();
    var watcher = gulp.watch(pathConfig.ui.core.sass.src + '**/*.scss', gulp.parallel('devServ:reload:styles'));
    watcher.on('change', function(event) {
        changedFilePath = event;
    });
    cb();
}

It would still be good to not use the old task and have this as a function though. Can anybody tell me why my refactored version doesn't work and have any suggestions as to how this should look?


Solution

  • I've fixed this now. gulp.series and gulp.parallel return functions so there was no need to wrap stylesCompileIncremental and reloadCss inside another function ie. devServReloadStyles. As per Blaine's comment here.

    So my function:

    function devServReloadStyles(cb) {
        gulp.series(stylesCompileIncremental, reloadCss);
    cb();
    

    }

    Can just be assigned to a variable:

    const devServReloadStyles = gulp.series(stylesCompileIncremental, reloadCss);
    

    And my stylesWatch task is already calling devServReloadStyles:

    // Compile all Sass files and watch for changes
    function stylesWatch(cb) {
        createImportsGraph();
        var watcher = gulp.watch(pathConfig.ui.core.sass.src + '**/*.scss', gulp.parallel(devServReloadStyles));
        watcher.on('change', function(event) {
            changedFilePath = event;
        });
        cb();
    }
    

    So running gulp stylesWatch now runs the stylesCompileIncremental job (notice how devServReloadStyles doesn't show as it's not a function).

    enter image description here