Search code examples
javascriptnode.jsbuildgulp

Add a condition to run a gulp watch


I have a gulp watch task as following:

gulp.task("watch", () => {
  const watch = {
    'dev': [src_folder + '**/*.njk', src_js_folder + '**/*.js'],
    'css': [src_sass_folder + '**/*.scss']
  }
  gulp.watch(watch.dev, gulp.series("dev")).on("change", browserSync.reload);
  gulp.watch(watch.css, gulp.series("sass"));

});

gulp.task("dev", gulp.series("merge-json", "nunjucks", "sass", "js"));

So when there's any changes on *.sass files the sass task will run, and when there's changes on *.js and/or *.njk files the task dev will run.

The problem I'm having is when there are changes on *.sass, *.js and/or *.njk at the same time, the sass task will run twice in this case.

How can I skip the gulp.watch(watch.css, gulp.series("sass")); when the gulp.watch(watch.dev, gulp.series("dev")).on("change", browserSync.reload); is already run.


Solution

  • Problem

    The double execution of the sass task when running the watch task occurs because in the code you have shared you are effectively defining the sass task to run twice.

    gulp.task("watch", () => {
        const watch = {
            'dev': [src_folder + '**/*.njk', src_js_folder + '**/*.js'],
            'css': [src_sass_folder + '**/*.scss']
        }
    
        // 1st execution > The `dev` task is defined into the `gulp.series()` as part
        // of the combined tasks to run for this watcher, and, as `dev` contains the
        // `sass` task in it this will run it the first time.
        gulp.watch(watch.dev, gulp.series("dev")).on("change", browserSync.reload);
        
        // 2nd execution > This watcher have the `sass` task defined into the
        // `gulp.series()` as part of the combined tasks to run, this will run
        // the second time
        gulp.watch(watch.css, gulp.series("sass"));
    });
    
    // The `dev` task contains the`sass` task into the `gulp.series()` as part
    // of the combined tasks to run
    gulp.task("dev", gulp.series("merge-json", "nunjucks", "sass", "js"));
    

    Therefore, every time you run gulp dev the sass task will be executed only once, and every time you run gulp watch the sass task will be executed twice.

    Solution

    To solve this problem you could perhaps reorder the executions in a slightly different way. Here are some ideas of what some possible solutions might look like.

    - Possible Solution 1

    const paths = {
        njk: src_folder + '**/*.njk',
        js: src_js_folder + '**/*.js',
        sass: src_sass_folder + '**/*.scss'
    }
    
    gulp.task("watch", () => {
        gulp.watch([
                paths.njk,
                paths.js,
                paths.sass
            ],
            gulp.series("dev")
        ).on("change", browserSync.reload);
    });
    
    gulp.task("dev", gulp.series("merge-json", "nunjucks", "sass", "js"));
    

    In this example, we define the sass task as part of the combined tasks to run defined within the gulp.series for the dev task. This will allow us to run gulp dev and execute all those tasks only once. It will also allow us to run gulp watch and execute the tasks defined for the dev task only once each time the files defined in paths are updated.

    - Possible Solution 2

    const paths = {
        njk: src_folder + '**/*.njk',
        js: src_js_folder + '**/*.js',
        sass: src_sass_folder + '**/*.scss'
    }
    
    gulp.task("watch", () => {
        gulp.watch([
                paths.njk,
                paths.js,
            ],
            gulp.series("dev")
        ).on("change", browserSync.reload);
        gulp.watch(paths.sass, gulp.series("sass");
    });
    
    gulp.task("dev", gulp.series("merge-json", "nunjucks", "js"));
    
    gulp.task("another_extra_task", gulp.series("dev", "sass"));
    

    In this example, we removed the sass task from the combined tasks to run for the dev task, also, we defined the another_extra_task task where we are combining the dev and sass tasks. This will allow us to run gulp another_extra_task and execute all the combined tasks defined for dev and the sass task, but also, it will allow us to run gulp watch without repeating the execution of the sass task since in the first watcher we execute the dev task where the sass task isn't defined anymore and we just execute it with the second watcher.

    Conclusion

    Since the definition of the tasks depends on each particular use case, I recommend you try to reorder the execution of them in a more granular way. See the following reference which explains how to avoid duplicating tasks https://gulpjs.com/docs/en/api/series#avoid-duplicating-tasks

    I hope these possible solutions help you to understand the problem you are having in the code you have shared!