Controlling Task Order and Concurrency in Gulp 4 with series() and parallel()
Learn how Gulp 4's series() and parallel() helpers control task order and concurrency, with a concrete gulpfile example, common pitfalls, and verification steps.
10 Aug 2026, 11:08 UTC

Useful answer
In Gulp 4, series() runs tasks one after another, while parallel() runs independent tasks at the same time. By combining them you can define a build pipeline that cleans first, then compiles CSS and JS concurrently, and finally runs revisioning.
How it works – a worked configuration
Assume you have three task functions: clean, styles, scripts, and a revision step revAssets. Each task must return a stream, promise, child process, or call a callback; otherwise Gulp treats it as synchronous and may hang.
const { src, dest, series, parallel } = require('gulp');
const del = require('del');
const sass = require('gulp-sass')(require('sass'));
const uglify = require('gulp-uglify');
const rev = require('gulp-rev');
function clean() {
return del(['dist']);
}
function styles() {
return src('src/scss/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(dest('dist/css'));
}
function scripts() {
return src('src/js/**/*.js')
.pipe(uglify())
.pipe(dest('dist/js'));
}
function revAssets() {
return src(['dist/css/**/*.css', 'dist/js/**/*.js'])
.pipe(rev())
.pipe(dest('dist'))
.pipe(rev.manifest())
.pipe(dest('dist'));
}
// Export a composite build task
exports.build = series(clean, parallel(styles, scripts), revAssets);
When you run gulp build:
cleanfinishes completely before anything else starts.- Once cleaning is done,
stylesandscriptsare launched concurrently; Gulp does not wait for one to finish before starting the other. - Only after both parallel tasks have completed does
revAssetsbegin.
Limits and common mistakes
Missing return or callback
If a task function does not return a stream/promise or call its callback, Gulp assumes the task finished immediately. This breaks the ordering guarantees of series() and can cause later tasks to start while earlier work is still running.
// ❌ Incorrect – no return
function styles() {
src('src/scss/**/*.scss')
.pipe(sass())
.pipe(dest('dist/css'));
}
Fix by returning the stream or returning a promise.
Mixing Gulp 3.x style task definitions
In Gulp 4, gulp.task('name', fn) is ignored when you later reference the task via series() or parallel(). The task will appear as “not found” and the build will fail silently.
Either export the function directly (as shown above) or, if you must keep gulp.task, assign the result to an exported constant:
exports.styles = gulp.task('styles', function () {
return src('src/scss/**/*.scss')
.pipe(sass())
.pipe(dest('dist/css'));
});
Excessive parallelism
Running many CPU‑ or I/O‑heavy tasks in parallel can saturate resources and actually slow the build, or cause race conditions when tasks write to the same files. Limit parallelism to truly independent work, and consider using gulp.watch or a concurrency‑limiting plugin if you need to run many similar tasks.
Verification steps
- Check Gulp version:
gulp -v(should be 4.0.0 or later). - Save the configuration above to
gulpfile.jsin an empty project. - Run
gulp buildand observe the terminal output:cleanfinishes, then you see bothstylesandscriptslogs interleaved, followed byrevAssets. - Introduce an error in one parallel task (e.g.,
throw new Error('fail styles');insidestyles) and run again; the other parallel task (scripts) should still run to completion before the build stops, proving independent execution.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.