Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gulp-image-resize to generate multiple output sizes

I'd like to use gulp to generate a bunch of different image sizes and optimize them at the same time. I think there are two approaches to this problem:

The first is that you could create n different tasks for each size, then create a master task that calls each resize task. The master task might look something like:

gulp.task('resize_images',['resize_100','resize_300','resize_800','resize_1000']);

This seems ok, and you'd get good parallelization, but there is a lot of duplicated code for each task which means maintaining it could be a nightmare if the list of sizes grows large enough.

The other idea I'd had was to create a single task, but use a for loop within it to iterate over each size. Like so:

var gulp = require('gulp');
var imageminWebp = require('imagemin-webp');
var imageResize = require('gulp-image-resize');
var notify = require('gulp-notify');
var os = require('os');
var parallel = require('concurrent-transform');
var pipes = require('gulp-pipes');

gulp.task('resize_images', function() {

    var sizes = [100,300,800,1000,2000];
    var stream;

    for (size in sizes) {
        stream = gulp.src('images/master/**/*.{jpg,png,tiff}')
            .pipe(parallel(
                    imageResize({
                        width:  sizes[size],
                        height: sizes[size],
                        upscale: false
                }),
                os.cpus().length
            ))
           .pipe(pipes.image.optimize())
           .pipe(gulp.dest('images/derivative/' + sizes[size] + '/'))
           .pipe(imageminWebp({quality: 75})())
           .pipe(gulp.dest('images/derivative/' + sizes[size] + '/'))
   }
   return stream;
});

This seems ok, but doesn't feel gulp-y for some reason. For example, notifications are weird with the solution above - I'd like to notify when each is size is done processing, which I get for free with the single master task. Is there a better way to accomplish what I'm trying to do?

like image 597
septagram Avatar asked Mar 04 '16 17:03

septagram


2 Answers

Remember: Gulp is just JavaScript.

There's nothing magical about gulp.task. You don't have to put everything in a Gulpfile inside of a task. Tasks are just functions.

You can leverage this fact and dynamically generate a bunch of tasks based on certain parameters, so you don't have duplicated code all over the place. In your case you can generate one task per image size that you want to create:

var resizeImageTasks = [];

[100,300,800,1000,2000].forEach(function(size) {
  var resizeImageTask = 'resize_' + size;
  gulp.task(resizeImageTask, function() {
    return gulp.src('images/master/**/*.{jpg,png,tiff}')
      .pipe(imageResize({
         width:  size,
         height: size,
         upscale: false
       }))
      .pipe(pipes.image.optimize())
      .pipe(gulp.dest('images/derivative/' + size + '/'))
      .pipe(imageminWebp({quality: 75})())
      .pipe(gulp.dest('images/derivative/' + size + '/'))
  });
  resizeImageTasks.push(resizeImageTask);
});

gulp.task('resize_images', resizeImageTasks);
like image 177
Sven Schoenung Avatar answered Nov 06 '22 15:11

Sven Schoenung


For Gulp 4:

var imagemin = require('gulp-imagemin');
var imageResize = require('gulp-image-resize');
var rename = require("gulp-rename");

function images(cb) {
  [100, 300, 800, 1000, 2000].forEach(function (size) {
    gulp.src('src/images/**/*.{jpg,jpeg,png}')
      .pipe(imageResize({ width: size }))
      .pipe(rename(function (path) { path.basename = `${path.basename}@${size}w`; }))
      .pipe(imagemin())
      .pipe(gulp.dest('dist/images'))
  });
  cb();
}

The callback is used to signal async completion (required by Gulp 4).

like image 6
Courtney Pattison Avatar answered Nov 06 '22 17:11

Courtney Pattison