Control Gulp output paths with gulp.src base and gulp.dest
Use gulp.src globs with an explicit base, pipe JavaScript through gulp-uglify, and write output with gulp.dest; verify with --verbose and inspect dist/js.
06 Dec 2025, 16:53 UTC

Problem and useful takeaway
A build task that lists JavaScript files by name breaks whenever a file is added, removed, or renamed. The practical fix is to let gulp.src select files with a glob, control the output folder structure with base, pipe the vinyl stream through gulp-uglify, and write with gulp.dest. Return the stream so Gulp knows when the task finishes; the pipeline is lazy and processes files as they are consumed.
Worked configuration
Assumes Gulp 4.x, a locally installed gulp, and gulp-uglify wrapping UglifyJS 2. Gulp streams carry vinyl file objects that include path and contents, so plugins can transform contents without writing to disk until gulp.dest runs. Run the task from the project root as a normal user; do not use sudo for locally installed node_modules.
const gulp = require('gulp');
const uglify = require('gulp-uglify');
exports.minify = function minify() {
return gulp.src('src/scripts/**/*.js', { base: 'src/scripts' })
.pipe(uglify())
.pipe(gulp.dest('dist/js'));
};
src/scripts/utils/helpers.js becomes dist/js/utils/helpers.js. The explicit base removes src/scripts from the emitted path, so changing the glob does not change the output layout. Without gulp.dest, the stream produces no files; without return, Gulp may end the task before the stream finishes.
Output path comparison
| gulp.src call | base used | Output for src/scripts/utils/helpers.js |
|---|---|---|
| gulp.src('src/scripts/**/*.js', { base: 'src/scripts' }).pipe(gulp.dest('dist/js')) | src/scripts | dist/js/utils/helpers.js |
| gulp.src('src/**/*.js').pipe(gulp.dest('dist/js')) | Gulp derives base from the part of the glob before the first metacharacter | Verify with --verbose; output layout depends on the derived base |
Run and verify
Run in the project root:
./node_modules/.bin/gulp --verbose minify
Expected checks: the log should show the task starting and finishing with elapsed time. Then list output:
find dist/js -type f -name '*.js'
Confirm minification by comparing line counts and comments:
wc -l src/scripts/**/*.js dist/js/**/*.js
grep -R '//' dist/js | head
Minified files should have far fewer lines and little or no comment text. If grep shows original source comments, the pipeline did not transform the files or the task failed silently. Risks: gulp.dest overwrites existing files in dist/js; never point it at a source directory. gulp-uglify can throw a syntax error on ES2015+ modules; transpile first or use gulp-terser for modern syntax.
Limits and common mistakes
- Plugin order matters. Put transformations that must see readable source before minification; minifying twice is wasted work and can break already minified code.
- Missing
returnon the stream is a common Gulp 4 mistake: the task reports success before files are written. - Too many small pipelines increase overhead; keep one task per build stage instead of chaining many tiny gulp runs.
- Glob patterns select files at stream start. Files added after the stream starts are not included in that run.
- Plugins that read files synchronously block the stream and reduce the performance benefit of streaming.
- Do not pass the same destination as a source glob; that can overwrite inputs or create recursive output.
- When using gulp.watch, changes to gulpfile.js are not picked up until the watch process is restarted.
Rollback for generated output
Because gulp.dest writes files, the practical rollback is to delete only the generated output and re-run:
rm -rf dist/js
./node_modules/.bin/gulp minify
Run rm -rf dist/js only after confirming the path; it deletes generated build output, not source files. Source files remain unchanged.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.