如何为gulp watch添加条件,避免sass任务被重复触发执行
解决方案
方案1:使用状态锁规避重复执行
该方案改动最小,通过状态标记控制css监听的执行逻辑,保留原有的监听规则:
gulp.task("watch", () => { // 标记dev任务是否处于运行状态 let isDevRunning = false; const watch = { 'dev': [src_folder + '**/*.njk', src_js_folder + '**/*.js'], 'css': [src_sass_folder + '**/*.scss'] } // 包装dev任务,运行前后切换状态标记 const wrappedDevTask = gulp.series( (cb) => { isDevRunning = true; cb(); }, "dev", (cb) => { isDevRunning = false; cb(); } ); gulp.watch(watch.dev, wrappedDevTask).on("change", browserSync.reload); // css监听回调中先判断状态,dev运行时跳过sass执行 gulp.watch(watch.css, (cb) => { if (isDevRunning) return cb(); gulp.series("sass")(cb); }); }); gulp.task("dev", gulp.series("merge-json", "nunjucks", "sass", "js"));
逻辑说明:
- dev任务执行前会先把状态标记设为true,执行完成后自动重置为false
- scss文件变更触发监听时,先判断dev是否正在运行,是则直接结束回调,否则执行sass任务
方案2:统一监听+动态判断执行逻辑(更推荐)
该方案从根源上避免任务重复触发,同时保留只修改scss时仅执行sass任务的性能优势:
gulp.task("watch", () => { // 统一监听所有需要监听的文件 const allWatchFiles = [ src_folder + '**/*.njk', src_js_folder + '**/*.js', src_sass_folder + '**/*.scss' ]; gulp.watch(allWatchFiles, (cb) => { // 提取本次变更的所有文件路径 const changedFiles = Object.keys(gulp.watch(allWatchFiles).changed()); // 判断是否存在除scss之外的文件变更 const hasNonScssChange = changedFiles.some(file => !file.endsWith('.scss')); if (hasNonScssChange) { // 存在js/njk变更时执行全量dev任务 return gulp.series("dev", (done) => { browserSync.reload(); done(); })(cb); } else { // 仅scss变更时只执行sass任务 return gulp.series("sass")(cb); } }); }); gulp.task("dev", gulp.series("merge-json", "nunjucks", "sass", "js"));
逻辑说明:
- 不再分开监听不同类型的文件,统一监听所有目标文件
- 每次触发变更时先判断变更文件的类型,根据类型选择要执行的任务,不会出现同一场景下多个任务同时触发的问题
内容的提问来源于stack exchange,提问作者Renaud is Not Bill Gates
相关产品推荐
相关产品推荐

