Using Gulp.js, I want to be able to be able to compile individual files in my js folder as normal, but concatenate content placed in subdirectories and assign the folder name to the concatenated file. (there's also some linting and minification going on)
Example Source
|-- js/
| |-- main/
| | |-- script1.js
| | |-- script2.js
| | |-- script3.js
| |-- detects/
| | |-- scriptA.js
| | |-- scriptB.js
| | |-- scriptC.js
| |-- myplugin.js
| |-- myplugin2.js
Example Output
|-- js/
| |-- myplugin.js
| |-- myplugin.min.js
| |-- myplugin2.js
| |-- myplugin2.min.js
| |-- main.js
| |-- main.min.js
| |-- detects.js
| |-- detects.min.js
What I've tried
gulp.task('scripts', ['clean'], function() {
return gulp.src('src/js/*')
.pipe(plumber())
.pipe(flatten())
.pipe(tap(function (file, t) {
if ( file.stat.isDirectory() ) {
var name = file.relative + '.js';
return gulp.src(file.path + '/*.js')
.pipe(concat(name))
.pipe(header(banner.full, { package : package }))
.pipe(gulp.dest(paths.scripts.output))
.pipe(rename({ suffix: '.min.' + Date.now() }))
.pipe(uglify())
.pipe(header(banner.min, { package : package }))
.pipe(gulp.dest(paths.scripts.output));
}
}))
.pipe(header(banner.full, { package : package }))
.pipe(gulp.dest(paths.scripts.output))
.pipe(rename({ suffix: '.min.' + Date.now() }))
.pipe(uglify())
.pipe(header(banner.min, { package : package }))
.pipe(gulp.dest(paths.scripts.output));
});
This actually works, but I don't like that I'm repeating code both in and after gulp-tap. Ideally I should be able to do something like this and have it feed back into the stream:
gulp.task('scripts', ['clean'], function() {
return gulp.src('src/js/*')
.pipe(plumber())
.pipe(flatten())
.pipe(tap(function (file, t) {
if ( file.stat.isDirectory() ) {
var name = file.relative + '.js';
return gulp.src(file.path + '/*.js')
.pipe(concat(name));
}
}))
.pipe(header(banner.full, { package : package }))
.pipe(gulp.dest(paths.scripts.output))
.pipe(rename({ suffix: '.min.' + Date.now() }))
.pipe(uglify())
.pipe(header(banner.min, { package : package }))
.pipe(gulp.dest(paths.scripts.output));
});
However, the subdirectory files are never compiled to the dest this way. other things I've tried that have not worked either:
1
.pipe(tap(function (file, t) {
if ( file.stat.isDirectory() ) {
var name = file.relative + '.js';
t.through(gulp.src(file.path + '/*.js')
.pipe(concat(name)));
}
}))
2
.pipe(tap(function (file, t) {
if ( file.stat.isDirectory() ) {
var name = file.relative + '.js';
.pipe(gulp.src(file.path + '/*.js')
.pipe(concat(name)));
}
}))
3
.pipe(tap(function (file, t) {
if ( file.stat.isDirectory() ) {
var name = file.relative + '.js';
gulp.src(file.path + '/*.js')
.pipe(concat(name));
}
}))
4
.pipe(tap(function (file, t) {
var scripts;
if ( file.stat.isDirectory() ) {
var name = file.relative + '.js';
scripts = gulp.src(file.path + '/*.js')
.pipe(concat(name));
}
return scripts;
}))
I've got functioning code so I'm not totally stuck, but I know there's a better way to do this. I would also like to be checking for a .js extension before running my uglifying and minifying (something covered for styles already because I'm only grabbing .scss files). Any insights here would be greatly appreciated.
You can use lazypipe to build up reusable processing pipelines.
Once you've identified the "reusable" behaviour you can convert it into a reusable block and invoke it multiple times.
In your case the repeated processing are these calls:
.pipe(header(banner.full, { package : package }))
.pipe(gulp.dest(paths.scripts.output))
.pipe(rename({ suffix: '.min.' + Date.now() }))
.pipe(uglify())
.pipe(header(banner.min, { package : package }))
.pipe(gulp.dest(paths.scripts.output));
So convert the calls into a reusable pipeline (see note at the bottom):
var lazypipe = require('lazypipe');
//...
var process = lazypipe()
.pipe(header, banner.full, { package : package })
.pipe(gulp.dest, 'paths.scripts.output')
.pipe(rename, { suffix: '.min.' + Date.now() })
.pipe(uglify)
.pipe(header, banner.min, { package : package })
.pipe(gulp.dest, paths.scripts.output);
And then you can use it multiple times:
gulp.task('scripts', ['clean'], function() {
//...
return gulp.src('src/js/*')
.pipe(plumber())
.pipe(flatten())
.pipe(tap(function (file, t) {
if ( file.stat.isDirectory() ) {
var name = file.relative + '.js';
return gulp.src(file.path + '/*.js')
.pipe(concat(name))
.pipe(handle);
.pipe(process()) // <----- here
}
}))
.pipe(process()) // <----- and here
});
Everything together:
gulp.task('scripts', ['clean'], function() {
// Define reusable pipeline.
var process = lazypipe()
.pipe(header, banner.full, { package : package })
.pipe(gulp.dest, 'paths.scripts.output')
.pipe(rename, { suffix: '.min.' + Date.now() })
.pipe(uglify)
.pipe(header, banner.min, { package : package })
.pipe(gulp.dest, paths.scripts.output);
return gulp.src('src/js/*')
.pipe(plumber())
.pipe(flatten())
.pipe(tap(function (file, t) {
if ( file.stat.isDirectory() ) {
var name = file.relative + '.js';
return gulp.src(file.path + '/*.js')
.pipe(concat(name))
.pipe(handle);
.pipe(process()) // <----- use it here
}
}))
.pipe(process()) // <----- and here
});
NOTE:
lazypipe uses lazy initialisation so the calls to .pipe() are different to regular Gulp streams.
Instead of calling the plugin like this: .pipe(header(banner.full, { package : package }))
You pass all as parameters to pipe: .pipe(header, banner.full, { package : package })
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With