如何解决同一Gulp任务中覆盖SCSS文件引发的无限循环问题?
Got it, let's break down why your task is stuck in an infinite loop first, then fix it step by step.
The Root Cause
Your original style task writes the sorted SCSS files back to the src/scss directory—exactly the folder your watcher is listening to. Every time the task finishes writing sorted files, the watcher detects a "change" and triggers the task again, creating an endless cycle. Even splitting tasks won't help if the sort task still modifies the watched source files.
The Solution
We'll split the workflow into two isolated tasks (sorting and compiling) and use a plugin to prevent unnecessary file writes that trigger the watcher. Here's how:
Step 1: Install Required Plugin
First, add gulp-changed to detect actual content changes (not just file timestamp updates):
npm install gulp-changed --save-dev
Step 2: Updated Gulpfile Code
// Load plugins const { gulp, watch, src, dest, series } = require('gulp'), browserSync = require('browser-sync').create(), postcss = require('gulp-postcss'), sortProperties = require('postcss-sorting'), sassParser = require('postcss-scss'), sass = require('gulp-sass'), changed = require('gulp-changed'); // New: Detect real content changes // Load CSS property orders for 'postcss-sorting' const propertySortOrder = require('./propertySortOrder'); // 1. Task: Sort SCSS properties (only modify files with actual content changes) const sortScss = () => { return src('src/scss/**/*.scss') // Only process files where content differs from the existing file .pipe(changed('src/scss', { hasChanged: changed.compareContents })) .pipe(postcss([sortProperties(propertySortOrder)], { syntax: sassParser })) .pipe(dest('src/scss')); }; // 2. Task: Compile sorted SCSS to CSS const compileScss = () => { return src('src/scss/**/*.scss') .pipe(sass().on('error', sass.logError)) .pipe(dest('dist/css')) // Matches your requirement to output to dist/css .pipe(browserSync.stream()); }; // Combined workflow: Sort first, then compile const style = series(sortScss, compileScss); // Start Server const startServer = (done) => { browserSync.init({ server: { baseDir: './' }, injectChanges: true }); done(); }; // Watch File Changes const watchFileChanges = (done) => { watch('src/scss/**/*.scss', style); done(); }; // Export tasks exports.start = series(startServer, watchFileChanges); exports.style = style; exports.sortScss = sortScss; exports.compileScss = compileScss;
Key Fixes Explained
gulp-changedwithcompareContents: This ensures thesortScsstask only writes to the source directory if the sorted content is different from the original file. No unnecessary writes = no false "change" triggers for the watcher.- Isolated Tasks: Separating sorting and compiling makes the workflow easier to debug and maintain. The combined
styletask runs them in sequence only when a real change is detected. - Corrected Output Path: I updated the compile output to
dist/cssto match your original requirement (your code hadsrc/csswhich was likely a typo).
Testing It Out
When you modify a file in src/scss:
- The watcher triggers the
styletask sortScssruns, sorts the properties, and writes back tosrc/scss(only if content changed)compileScssruns, takes the sorted SCSS, and compiles it todist/css- No further triggers happen because
sortScsswon't rewrite the file again (content is already sorted)
Content的提问来源于stack exchange,提问作者Lachrimae

