web-dev-qa-db-fra.com

création de tâches à l'aide d'une boucle [gulp]

J'essaye de créer dynamiquement des tâches (minify et concat) basées sur jsFiles object. La touche donnera le nom du fichier de destination et le tableau contient les fichiers src . Quand je lance gulp, je vois tous les noms de tâches en cours d'exécution, mais il n'écrit que la dernière clé qui est group2.js dans ce cas. Quel est le problème ici?

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

Une autre option consiste à utiliser des fonctions de boucle de tableau fonctionnel combinées avec Object.keys, comme ceci:

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

J'ai l'impression que c'est un peu plus propre, parce que vous avez la boucle et la fonction au même endroit, donc c'est plus facile à maintenir.

22
OverZealous

Capturez la valeur de la variable 'key' à chaque itération en utilisant IIFE . Dans votre exemple, au moment de la boucle d'invocation de concaténage, la boucle sera déjà terminée et la variable key aura la dernière valeur.

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

}

Pour une explication détaillée, voir la section Fonctions de fermeture - Eviter le problème de référence

6
oaleynik

Avec Gulp # 4.0, j'aime bien utiliser gulp.parallel () tel que:

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

Travailler pour moi et j'adore ça! Merci à OverZealous de me montrer le chemin.

2
Frost Michael

la solution de cmancre fonctionne bien ... mais voici la version modifiée et fonctionnelle que j'utilise actuellement:

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

Solution basée sur 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);
0
cmancre