creating tasks using a loop [gulp]
I'm trying to dynamically create tasks (minify and concat) based on jsFiles object. The key will give the destination file name and the array contains the src files. When I run gulp I see all the tasks names being ran but it only writes the last key which is group2.js in this case. What's wrong here?
// imports here
var jsFiles =
{
group1:[file1.js,file2.js],
group2:[file2.js,file3.js]
};
for (var key in jsFiles)
{
gulp.task(key, function() {
return gulp.src(jsFiles[key])
.pipe(jshint())
.pipe(uglify())
.pipe(concat(key + '.js')) // <- HERE
.pipe(gulp.dest('public/js'));
});
}
var defaultTasks = [];
for (var key in jsFiles)
{
defaultTasks.push(key);
}
gulp.task('default', defaultTasks);
Solution 1:
Another option is to use functional array looping functions combined with Object.keys
, like so:
var defaultTasks = Object.keys(jsFiles);
defaultTasks.forEach(function(taskName) {
gulp.task(taskName, function() {
return gulp.src(jsFiles[taskName])
.pipe(jshint())
.pipe(uglify())
.pipe(concat(key + '.js'))
.pipe(gulp.dest('public/js'));
});
});
I feel like this is a little cleaner, because you have the loop and the function in the same place, so it's easier to maintain.
Solution 2:
Capture the value of 'key' variable on each iteration using IIFE. In your example, at the moment of concat invocation loop will be finished already and variable key will have the last value.
for (var key in jsFiles)
{
(function(key) {
gulp.task(key, function() {
return gulp.src(jsFiles[key])
.pipe(jshint())
.pipe(uglify())
.pipe(concat(key + '.js')) // <- HERE
.pipe(gulp.dest('public/js'));
});
})(key);
}
For detailed explanation see this function closures - Avoiding the Reference Problem section
Solution 3:
Using Gulp#4.0, I like the use of gulp.parallel() such as :
var plugins = require('gulp-load-plugins');
var $ = plugins();
var jsFiles = {
// Libraries required by Foundation
"jquery" : [
"bower_components/jquery/dist/jquery.js",
"bower_components/motion-ui/dist/motion-ui.js",
"bower_components/what-input/dist/what-input.js"
],
"angular" : [
"bower_components/angular/angular.min.js",
"bower_components/angular-animate/angular-animate.min.js",
"bower_components/angular-aria/angular-aria.min.js",
"bower_components/angular-material/angular-material.min.js",
"bower_components/angular-messages/angular-messages.min.js",
"bower_components/angular-sanitize/angular-sanitize.min.js",
"bower_components/angular-ui-i18n/angular-ui-i18n.min.js"
],
// Core Foundation files
"foundation-sites" : [
"bower_components/foundation-sites/dist/js/foundation.js"
],
// Dropzone Library
"dropzone" : [
"bower_components/dropzone/dist/dropzone.js",
"bower_components/ng-dropzone/dist/ng-dropzone.min.js"
]
};
var defaultTasks = Object.keys(jsFiles);
defaultTasks.forEach(function (libName) {
gulp.task( 'scripts:'+libName, function () {
return gulp.src(jsFiles[libName])
//.pipe($.jshint()) // if you want it
//.pipe($.uglify()) // if you like it
//.pipe($.concat(libName+'.js')) // .min.js if you Uglified it
.pipe(gulp.dest('dist/lib/'+libName));
});
});
gulp.task( 'bundle_javascript_dependencies',
gulp.parallel(
defaultTasks.map(function(name) { return 'scripts:'+name; })
)
);
gulp.task('build',
gulp.series(
'clean',
gulp.parallel( /* Any other task of function */ 'bundle_javascript_dependencies' )
)
);
Working for me and I love it ! Thanks to OverZealous to have show me the way.
Solution 4:
cmancre solution work fine... but here the modified and working one i'm currently using:
var jsFiles =
{
group1:[file1.js,file2.js],
group2:[file2.js,file3.js]
};
var defaultTasks = [];
function createTask(key)
{
gulp.task(key, function() {
return gulp.src(jsFiles[key])
.pipe(uglify())
.pipe(concat(key + '.js'))
.pipe(rename({suffix: ".min"})) //Will create group1.min.js
.pipe(gulp.dest('./assets/js'));
});
}
for (var key in jsFiles)
{
createTask(key);
defaultTasks.push(key);
}
gulp.task('default', defaultTasks, function(){
for (var key in jsFiles)
{
//Will watch each js defined in group1 or group2
gulp.watch(jsFiles[key], [key])
}
});