2

I have a situation where I was currently uglifying all JavaScript files even if they were already compressed, which obviously isn't a great idea.

My respective task was:

gulp.task('uglify', ['scripts'], function() {
    return gulp.src('./js/scripts.js')
        .pipe(rename({suffix: '.min'}))
        .pipe(uglify({
            mangle: false
        }))
        .pipe(gulp.dest('./js'));
});

scripts.js was a file that was previously concatenated together, but obviously if there was some already compressed files in there then they are going to get uglified again, which we are trying to avoid.

So I did a search around and have been looking at processing all the files again rather than working off of the unminified (the file that just contains concatenated files) version so that I have more control over each file.

I looked into using gulp-ignore and gulp-if and gulp-if seems to possibly be what I want; however I'm not 100% sure how streams operate in Gulp - when you pass it a list of files does it loop through the tasks for each file or just run once?

I'm curious because if it runs through for each file I was working on doing something like this:

gulp.task('uglify', ['scripts'], function() {
    return gulp.src(js_scripts)
        .pipe(gulpif(condition, uglify({mangle: false})))
        .pipe(concat('scripts.min.js'))
        .pipe(gulp.dest('./js'));
});

Where condition was something that checked to see if the file had .min in the filename and if so, don't uglify it.

So my question is - if it loops through and I can run the condition on each file, how can I go about running tests on the filename and if it doesn't loop through then how can I achieve what I am trying to do here? Am I going to be forced to create two separate tasks, one for unminified and one for .min files and then at the end join them together?

Brett
  • 19,449
  • 54
  • 157
  • 290

2 Answers2

2

I think your example should do just that, uglify only the files that meet the condition, but pass all files to the next operator, reagrdless of the condition.

gulp.task('uglify', ['scripts'], function() {
    return gulp.src(js_scripts)
        .pipe(gulpif(condition, uglify({mangle: false})))
        .pipe(concat('scripts.min.js'))
        .pipe(gulp.dest('./js'));
});

There is an example in `gulp-if called 1: Conditionally filter content where it states:

Only uglify the content if the condition is true, but send all the files to the dist folder

I think it will send all the files down the stream even when there is something before the dist folder.

As for the looping question, the condition is checked per-file in the source, js_scripts here.

EDIT: You can use a function to check the filename condition

var condition = function (file) {
  // TODO: add business logic
  console.log(file.path);
  return true;
}

EDIT 2

As per @mark's and @Brett's comments and research, you can also use Regex to exclude already minified files, i.e. files with .min.js suffix:

gulp.task('uglify', ['scripts'], function() {
    return gulp.src(js_scripts)
        .pipe(gulpif('!**/*.min.js', uglify({mangle: false})))
        .pipe(concat('scripts.min.js'))
        .pipe(gulp.dest('./js'));
});
lofihelsinki
  • 2,491
  • 2
  • 23
  • 35
  • The condition in gulpif should accept regex, so this might work: `.pipe(gulpif(['', '!.min.*'], uglify({mangle: false})))` – lofihelsinki Feb 16 '18 at 15:05
  • Thanks, I will give it a try. But shouldn't the regex be something like: `['**', '!*.min.js']` as negation alone doesn't work? – Brett Feb 16 '18 at 15:18
  • Probably. I'm not 100% sure if regex works with gulpif at all, then you need to use the condition function. – lofihelsinki Feb 16 '18 at 15:23
  • 1
    Negation alone does work so .pipe(gulpif('!*.min.js', uglify())) will exclude *.min.js files from being uglified. It looks like you are trying to pass a glob as the condition, i.e., in your [..] , I don't believe that works in gulp-if. – Mark Feb 16 '18 at 16:12
  • 1
    @Mark Well I know negation only doesn't in `src(...)` but I assume it works in this case because you already have a set of files? As for globs, it should work as it states on in the documentation that it supports any of the conditions supported by [gulp-match](https://github.com/robrich/gulp-match). – Brett Feb 16 '18 at 17:10
1

With the help of @lofihelsinki's answer and @mark's comment I was able to come up with a solution.

Whilst these led me in the right direction, I still had to tweak some code through trial and error, so I was unable to accept the answer, but I wanted to credit them since they led me to the solution.

The final solution was:

gulp.task('uglify', ['scripts'], function() {
    return gulp.src(js_scripts)
        .pipe(gulpif('!**/*.min.js', uglify({mangle: false})))
        .pipe(concat('scripts.min.js'))
        .pipe(gulp.dest('./js'));
});

I tried the suggestion by @Mark but it seems that even though you have the files in the stream you still have to respect the folder location; so I had to change his suggestion of '!*.min.js' to '!**/*.min.js'; this will now only uglify scripts that do not contain .min.js in the filename and the ones that do will get passed through untouched.

Brett
  • 19,449
  • 54
  • 157
  • 290
  • Thanks, edited the answer accordingly. I think the original suggestion of a condition function would also work, but of course regex is shorter & more convenient. – lofihelsinki Feb 19 '18 at 08:03