Создание задач с использованием цикла [gulp]

Я пытаюсь динамически создавать задачи (minify и concat) на основе объекта jsFiles. Клавиша даст имя целевого файла, а массив содержит файлы src. Когда я запускаю gulp, я вижу, что все имена задач запущены, но в этом случае он записывает только последний ключ, который является group2.js. Что здесь не так?

// 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);

Ответы

Ответ 1

Другим вариантом является использование функций циклического цикла с функциональным циклом в сочетании с Object.keys, например:

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'));
   });
});

Мне кажется, что это немного чище, потому что у вас есть петля и функция в одном и том же месте, поэтому ее легче поддерживать.

Ответ 2

Захват значения переменной "ключ" на каждой итерации с использованием IIFE. В вашем примере, в момент цикла concat invocation будет завершен, и ключ переменной будет иметь последнее значение.

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);

}

Подробное объяснение см. в закрытии функций - Избегание раздела справочной проблемы

Ответ 3

Используя Gulp # 4.0, мне нравится использование gulp.parallel(), например:

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' )
   )
);

Работаю для меня, и мне это нравится! Благодаря OverZealous, чтобы показать мне путь.

Ответ 4

Решение основано на jslinterrors.com/dont-make-functions-within-a-loop:

var jsFiles = 
{
    group1:[file1.js,file2.js],
    group2:[file2.js,file3.js]
};

function createTask(key)
{
   return gulp.src(jsFiles[key])
        .pipe(jshint())
        .pipe(uglify())
        .pipe(concat(key + '.js'))
        .pipe(gulp.dest('public/js'));

}

for (var key in jsFiles)
{
    createTask(key);
}

var defaultTasks = [];
for (var key in jsFiles)
{
    defaultTasks.push(key);
}
gulp.task('default', defaultTasks);

Ответ 5

cmancre solution отлично работает... но здесь измененный и рабочий, который я сейчас использую:

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]) 
    }
});