web-dev-qa-db-fra.com

Scripts concat dans l'ordre avec Gulp

Supposons, par exemple, que vous construisez un projet sur Backbone ou autre, et que vous ayez besoin de charger des scripts dans un certain ordre, par exemple. underscore.js doit être chargé avant backbone.js.

Comment puis-je le faire pour concaténer les scripts afin qu’ils soient en ordre? 

// JS concat, strip debugging and minify
gulp.task('scripts', function() {
    gulp.src(['./source/js/*.js', './source/js/**/*.js'])
    .pipe(concat('script.js'))
    .pipe(stripDebug())
    .pipe(uglify())
    .pipe(gulp.dest('./build/js/'));
});

J'ai le bon ordre de scripts dans mon source/index.html, mais étant donné que les fichiers sont classés par ordre alphabétique, gulp va concatéler underscore.js après le backbone.js et l'ordre des scripts dans mon source/index.html n'a pas d'importance.

Quelqu'un a-t-il une idée à ce sujet?

La meilleure idée que j'ai est de renommer les scripts du fournisseur avec 1, 2, 3 afin de leur donner le bon ordre, mais je ne suis pas sûr si j'aime ça.

En apprenant plus, j'ai trouvé que Browserify est une excellente solution. Cela peut être pénible au début, mais c’est génial.

181
Michael Joseph Aubry

J'ai récemment eu un problème similaire avec Grunt lors de la construction de mon application AngularJS. Voici une question j'ai posté.

Ce que j'ai fini par faire est de lister explicitement les fichiers dans l'ordre dans la configuration Grunt. Donc, il ressemblait à:

[
  '/path/to/app.js',
  '/path/to/mymodule/mymodule.js',
  '/path/to/mymodule/mymodule/*.js'
]

Et les choses ont fonctionné. Et Grunt est apparemment assez intelligent pour ne pas inclure deux fois le même fichier.

Cela fonctionne de la même manière avec Gulp.

189
Chad Johnson

Une autre chose qui aide si vous avez besoin de fichiers à venir après un blob de fichiers, est d'exclure des fichiers spécifiques de votre glob, comme ceci:

[
  '/src/**/!(foobar)*.js', // all files that end in .js EXCEPT foobar*.js
  '/src/js/foobar.js',
]

Vous pouvez combiner ceci avec la spécification de fichiers devant venir en premier, comme expliqué dans la réponse de Chad Johnson.

131
OverZealous

J'ai utilisé le plugin gulp-order mais cela n'a pas toujours abouti, comme le montre mon dépassement de pile post module de nœud gulp-order avec les flux fusionnés . En parcourant les documents Gulp, je suis tombé sur le module streamque, qui a très bien fonctionné pour spécifier l'ordre de la concaténation dans mon cas. https://github.com/gulpjs/gulp/blob/master/docs/recipes/using-multiple-sources-in-one-task.md

Exemple de comment je l'ai utilisé ci-dessous

var gulp         = require('gulp');
var concat       = require('gulp-concat');
var handleErrors = require('../util/handleErrors');
var streamqueue  = require('streamqueue');

gulp.task('scripts', function() {
    return streamqueue({ objectMode: true },
        gulp.src('./public/angular/config/*.js'),
        gulp.src('./public/angular/services/**/*.js'),
        gulp.src('./public/angular/modules/**/*.js'),
        gulp.src('./public/angular/primitives/**/*.js'),
        gulp.src('./public/js/**/*.js')
    )
        .pipe(concat('app.js'))
        .pipe(gulp.dest('./public/build/js'))
        .on('error', handleErrors);
});
17
dtothefp

Avec gulp-useref, vous pouvez concaténer chaque script déclaré dans votre fichier d’index, dans l’ordre dans lequel vous le déclarez. 

https://www.npmjs.com/package/gulp-useref

var $ = require('gulp-load-plugins')();
gulp.task('jsbuild', function () {
  var assets = $.useref.assets({searchPath: '{.tmp,app}'});
  return gulp.src('app/**/*.html')
    .pipe(assets)
    .pipe($.if('*.js', $.uglify({preserveComments: 'some'})))
    .pipe(gulp.dest('dist'))
    .pipe($.size({title: 'html'}));
});

Et dans le HTML, vous devez déclarer le nom du fichier de construction que vous voulez générer, comme ceci:

<!-- build:js js/main.min.js -->
    <script src="js/vendor/vendor.js"></script>
    <script src="js/modules/test.js"></script>
    <script src="js/main.js"></script>

Dans votre répertoire de construction, vous aurez la référence à main.min.js qui contiendra vendor.js, test.js et main.js

12
SuperIRis

Le sort-stream peut également être utilisé pour garantir l'ordre spécifique des fichiers avec gulp.src. Exemple de code qui place le backbone.js toujours comme dernier fichier à traiter:

var gulp = require('gulp');
var sort = require('sort-stream');
gulp.task('scripts', function() {
gulp.src(['./source/js/*.js', './source/js/**/*.js'])
  .pipe(sort(function(a, b){
    aScore = a.path.match(/backbone.js$/) ? 1 : 0;
    bScore = b.path.match(/backbone.js$/) ? 1 : 0;
    return aScore - bScore;
  }))
  .pipe(concat('script.js'))
  .pipe(stripDebug())
  .pipe(uglify())
  .pipe(gulp.dest('./build/js/'));
});
6
fracz

J'ai mes scripts organisés dans des dossiers différents pour chaque paquet que je tire de bower, plus mon propre script pour mon application. Puisque vous allez lister l'ordre de ces scripts quelque part, pourquoi ne pas les lister dans votre fichier gulp? Pour les nouveaux développeurs de votre projet, il est bien que tous vos points de terminaison de script soient répertoriés ici. Vous pouvez le faire avec gulp-add-src :

gulpfile.js

var gulp = require('gulp'),
    less = require('gulp-less'),
    minifyCSS = require('gulp-minify-css'),
    uglify = require('gulp-uglify'),
    concat = require('gulp-concat'),
    addsrc = require('gulp-add-src'),
    sourcemaps = require('gulp-sourcemaps');

// CSS & Less
gulp.task('css', function(){
    gulp.src('less/all.less')
        .pipe(sourcemaps.init())
        .pipe(less())
        .pipe(minifyCSS())
        .pipe(sourcemaps.write('source-maps'))
        .pipe(gulp.dest('public/css'));
});

// JS
gulp.task('js', function() {
    gulp.src('resources/assets/bower/jquery/dist/jquery.js')
    .pipe(addsrc.append('resources/assets/bower/bootstrap/dist/js/bootstrap.js'))
    .pipe(addsrc.append('resources/assets/bower/blahblah/dist/js/blah.js'))
    .pipe(addsrc.append('resources/assets/js/my-script.js'))
    .pipe(sourcemaps.init())
    .pipe(concat('all.js'))
    .pipe(uglify())
    .pipe(sourcemaps.write('source-maps'))
    .pipe(gulp.dest('public/js'));
});

gulp.task('default',['css','js']);

Remarque: jQuery et Bootstrap ajoutés à des fins de démonstration de l'ordre. Il est probablement préférable d’utiliser des CDN pour ceux-ci car ils sont très utilisés et les navigateurs pourraient déjà les mettre en cache à partir d’autres sites.

5
prograhammer

Je viens d'ajouter des chiffres au début du nom du fichier:

0_normalize.scss
1_tikitaka.scss
main.scss

Cela fonctionne en avalant sans aucun problème.

3
user3360496

Essayez stream-series . Cela fonctionne comme merge-stream / event-stream.merge () sauf qu’au lieu d’entrelacement, il s’ajoute à la fin. Il ne vous oblige pas à spécifier le mode objet comme streamqueue , votre code en sort donc plus propre. 

var series = require('stream-series');

gulp.task('minifyInOrder', function() {
    return series(gulp.src('vendor/*'),gulp.src('extra'),gulp.src('house/*'))
        .pipe(concat('a.js'))
        .pipe(uglify())
        .pipe(gulp.dest('dest'))
});
2
Code Bling

Une autre méthode consiste à utiliser un plugin Gulp créé spécifiquement pour résoudre ce problème. https://www.npmjs.com/package/gulp-ng-module-sort

Il vous permet de trier vos scripts en ajoutant une .pipe(ngModuleSort()) en tant que telle: 

var ngModuleSort = require('gulp-ng-module-sort');
var concat = require('gulp-concat');

gulp.task('angular-scripts', function() {
    return gulp.src('./src/app/**/*.js')
        .pipe(ngModuleSort())
        .pipe(concat('angularAppScripts.js))
        .pipe(gulp.dest('./dist/));
});

En supposant une convention de répertoire de: 

|——— src/
|   |——— app/
|       |——— module1/
|           |——— sub-module1/
|               |——— sub-module1.js
|           |——— module1.js
|       |——— module2/
|           |——— sub-module2/
|               |——— sub-module2.js
|           |——— sub-module3/
|               |——— sub-module3.js
|           |——— module2.js
|   |——— app.js

J'espère que cela t'aides!

1
VinegarStrokes

merge2 semble être le seul outil de fusion de flux ordonné actif et mis à jour pour le moment.

1
Alexander Shutov

Je viens d'utiliser gulp-angular-filesort

function concatOrder() {

    return gulp.src('./build/src/app/**/*.js')
        .pipe(sort())
        .pipe(plug.concat('concat.js'))
        .pipe(gulp.dest('./output/'));
}
1
Maccurt

Pour moi, j'avais natualSort () et angularFileSort () dans le tuyau qui réorganisait les fichiers. Je l'ai enlevé et maintenant cela fonctionne bien pour moi

$.inject( // app/**/*.js files
    gulp.src(paths.jsFiles)
      .pipe($.plumber()), // use plumber so watch can start despite js errors
      //.pipe($.naturalSort())
      //.pipe($.angularFilesort()),
    {relative: true}))
1
casper123

J'ai essayé plusieurs solutions de cette page, mais aucune n'a fonctionné. J'avais une série de fichiers numérotés pour lesquels je voulais simplement être classés par nom de dossier alphabétique; ainsi, lorsqu'ils seraient redirigés vers concat(), ils seraient dans le même ordre. En d’autres termes, conservez l’ordre des entrées globantes. Facile, non?

Voici mon code de preuve de concept spécifique (print est juste pour voir la commande imprimée à la cli):

var order = require('gulp-order');
var gulp = require('gulp');
var print = require('gulp-print').default;

var options = {};

options.rootPath = {
  inputDir: process.env.INIT_CWD + '/Draft',
  inputGlob: '/**/*.md',
};

gulp.task('default', function(){
  gulp.src(options.rootPath.inputDir + options.rootPath.inputGlob, {base: '.'})
    .pipe(order([options.rootPath.inputDir + options.rootPath.inputGlob]))
    .pipe(print());
});

La raison de la folie de gulp.src? J'ai déterminé que gulp.src fonctionnait de manière asynchrone lorsque j'ai été en mesure d'utiliser une fonction sleep() (à l'aide d'un .map avec incrémentation de durée d'attente par index) pour ordonner la sortie du flux correctement. 

Le résultat de l'async de src signifie que les répertoires contenant plus de fichiers y figurent après les répertoires contenant moins de fichiers, car leur traitement a pris plus de temps.

0
Jeremy John

Je suis dans un environnement de module où tous sont dépendants du noyau et utilisent gulp. Donc, le module core doit être ajouté avant les autres. 

Ce que j'ai fait:

  1. Déplacez tous les scripts dans un dossier src
  2. Juste gulp-rename votre répertoire core à _core
  3. gulp garde l'ordre de votre gulp.src, mon concat src ressemble à ceci:

    concat: ['./client/src/js/*.js', './client/src/js/**/*.js', './client/src/js/**/**/*.js']
    

Cela prendra évidemment le _ comme premier répertoire de la liste (sorte naturelle?).

Note (angularjs): J'utilise ensuite gulp-angular-extender pour ajouter dynamiquement les modules au module core . Compilé, il ressemble à ceci:

angular.module('Core', ["ui.router","mm.foundation",(...),"Admin","Products"])

Où Admin et Products sont deux modules.

0
soyuka

Dans ma configuration gulp, je spécifie d'abord les fichiers du fournisseur, puis le tout (plus général), ensuite. Et cela place avec succès le fournisseur js avant les autres éléments personnalisés.

gulp.src([
  // vendor folder first
  path.join(folder, '/vendor/**/*.js'),
  // custom js after vendor
  path.join(folder, '/**/*.js')
])    
0
ProGrammar

si vous souhaitez commander des dépendances de bibliothèques tierces, essayez wiredep . En gros, ce paquet vérifie chaque dépendance de paquet dans bower.json, puis les câble pour vous.

0
zak.http