Search code examples
gulpgulp-uglifygulp-concat

Why is Gulp concatenating my output in the wrong order?


As shown in the following gulpfile.js, I am trying to compile jQuery, bootstrap.js, and a collection of Javascript snippets from a subfolder into a single app.js output file. It is working, except that the snippets from the subfolder are appearing at the top of the app.js output file, prior to jQuery being loaded.

How can I ensure that these files are output in the correct order?

const { src, dest, watch, series, parallel } = require('gulp');
const concat = require('gulp-concat');
const uglify = require('gulp-uglify');
var merge2 = require('merge2');

const files = {
  jsSrcPath: [
    '../node_modules/jquery/dist/jquery.js',
    '../node_modules/bootstrap/dist/js/bootstrap.js',
    'js/*.js'
  ],
  jsDstPath: '../public/js'
}

function jsTask(){
  return merge2(files.jsSrcPath.map(function (file) {
    return src(file)
  }))
  .pipe(concat('app.js'))
  .pipe(uglify())
  .pipe(dest(files.jsDstPath));
}

function watchTask(){
    watch(files.jsSrcPath, jsTask);
}

exports.default = series(
    jsTask,
    watchTask
);

Solution

  • There's something internal here going on, in my tests I saw the order was sometimes random, sometimes based on modification time, sometimes in order. In any case, best to use a tool to ensure our streams are always in the order we want them.

    gulp-order exists for this purpose. It can take specific paths and glob syntax, which you already have, so you can re-pass that to the plugin:

    const { src, dest, watch, series, parallel } = require('gulp');
    const concat = require('gulp-concat');
    const uglify = require('gulp-uglify');
    const order = require('gulp-order'); // Added
    var merge2 = require('merge2');
    
    const files = {
      jsSrcPath: [
        '../node_modules/jquery/dist/jquery.js',
        '../node_modules/bootstrap/dist/js/bootstrap.js',
        'js/*.js'
      ],
      jsDstPath: 'dist'
    }
    
    function jsTask() {
      return merge2(files.jsSrcPath.map(function (file) {
        return src(file)
      }))
        .pipe(order(files.jsSrcPath)) // Added
        .pipe(concat('app.js'))
        .pipe(uglify())
        .pipe(dest(files.jsDstPath));
    }
    
    function watchTask() {
      watch(files.jsSrcPath, jsTask);
    }
    
    exports.default = series(
      jsTask,
      watchTask
    );