Gulp: Minify and Optimize Images

Published:

|

Updated:

Images play a significant role on the web, not only enriching content but also serving as valuable tools for users (e.g., infographic, charts, and comparison screenshots), enhancing engagement and overall experience. In today's digital landscape, the prevalence of imagery on the internet is undeniable.

However, it's important to know that images often have large file sizes compared to other website assets like CSS, JS, and fonts. Leaving them unoptimized can negatively affect user experience like slow page loading speeds, ultimately driving visitors away from the website.

To mitigate such issues, serving properly optimized images is crucial for a good user experience. This involves employing various strategies, including scaling dimensions appropriately, minifying and compressing to reduce file sizes, and adopting modern image formats such as WebP.

So, in this tutorial, you'll learn how to use the Gulp task runner to set up automation for efficiently optimizing images (in different formats, including JPEG, PNG, and WebP).

Let's get started!

Gulp: Minify and Optimize Images

Why Optimizing Images Is Crucial

As mentioned above, delivering minified images is crucial for a couple of reasons. Below are some major reasons.

Firstly, with more people browsing the internet on mobile devices, serving unoptimized images can quickly consume precious data bandwidth that could otherwise be utilized for essential tasks.

For example, displaying large-resolution images (e.g., 1200 x 630 pixels) on phones, which typically have a maximum display width of 400px, results in unnecessary bandwidth consumption. Therefore, it's essential to create multiple sizes of images suitable for various devices, including desktop PCs, laptops, tablets, and mobile phones.

Secondly, uncompressed images carry a large file size due to metadata like EXIF, which provides information such as image width and height, often redundant for websites. Compressing images ensures that the smallest possible file size is served, conserving users' bandwidth and accelerating page loads.

Manual vs. Automated Image Optimization Methods

Depending on the requirements, there are cases where both manual and automatic image optimization methods are suitable. Consider the following two scenarios.

A website covering reviews of new graphics cards like the NVIDIA RTX 40 series would typically display several benchmarks and charts (thermals, in-game FPS, etc.). This means that optimizing images would only be done once per review, as new graphics cards are not launched frequently. So, manually optimizing images (using Figma or another image tool) might make sense and be acceptable here.

On the other hand, consider an online newspaper website that delivers news on K-Pop artists or groups like IVE or LE SSERAFIM. Obviously, the site would feature high-quality images of members and their moments (twice a week or so), entailing the optimization of numerous images in a short period.

In such a scenario, manual optimizations like resizing, minifying, and converting to different formats would be cumbersome and consume a lot of time (and that's not good news for a news website!).

Therefore, employing an automated image optimization solution that takes care of all these tasks would be ideal here, and this is the method we'll dive into IVE in this tutorial.

Brief Intro on Gulp

At its core, Gulp.js is essentially a task runner that speeds up frontend development by automating many common and repetitive tasks — such as minifying and concatenating CSS and JS, optimizing fonts and images, and converting Markdown into HTML.

However, as invaluable as it sounds, manually installing and configuring Gulp can take valuable hours, especially if you're a beginner in JavaScript. Luckily, I've got you covered with Essential Gulp Kit — a zero-config (no manual configuration required!) developer-friendly toolkit. Read on to learn more about it.

Enter Essential Gulp Kit

Essential Gulp Kit is an all-in-one solution that not only caters to all common front-end optimization requirements but offers complete image optimization features. These features include compressing and minifying PNG and JPG files, creating WebP and AVIF versions, resizing width and height, bulk processing, and more!

With Essential Gulp Kit, all you have to do is specify your input and output directories and use either the 1-click optimization preset files or the built-in npm run commands (via a terminal or command-line interface) to instantly process and optimize images.

The best part? It's completely independent of language and tech stack. Whether you code in TypeScript or JavaScript; use Vue.js or React; or build your site in Eleventy or Gatsby, Essential Gulp Kit works flawlessly out-of-the-box.

Prerequisites

Gulp requires Node.js to work. If Node isn't already installed on your PC, install and set it up following this tutorial: Node.js (nodejs) and npm Installation on Windows

Regarding the optimization plugin, while there are several plugins available like gulp-imagemin (Gulp wrapper for imagemin), I'll use gulp-sharp-responsive which is based on the Sharp image processor.

A Few Notes to Consider

To set clear expectations for the tutorial, here are a few considerations to keep in mind:

Individual Optimization Tasks

For the optimization tasks, I'll create one for each format: JPEG, PNG, and WebP. It's worth noting that all three tasks largely follow the same steps and code, albeit with different optimization settings for each image format (more on this later).

This way, you have the flexibility to run and implement relevant tasks as needed. However, as a bonus, I've also shared the steps to combine and run all tasks simultaneously below.

Default Image Compression Configurations

In the tutorial code below, Gulp and the image processor plugin (gulp-sharp-responsive) have been pre-configured with optimal settings. Nevertheless, feel free to customize these settings as needed, such as adjusting file names, input/output directories, and image quality settings.

Using IDE or Terminal

Ideally, you'd use an IDE like Visual Studio Code with an integrated terminal to conveniently execute the given commands/tasks. However, it's perfectly fine if you'd rather adopt a more traditional route via a CLI like Windows Terminal, Mac Terminal, or any other preferred method.

Steps to Optimize and Minify Images Using Gulp

Assuming you've installed Node and the npm dependency manager (if not, refer to this tutorial), follow the below steps to optimize images with Gulp.

Step 1: Install Gulp and Gulp Sharp Responsive Image Plugin

Start by navigating to the root directory of your website/project, where the package.json file is located.

Then, in the terminal, execute the following command to install both Gulp and Gulp Sharp Responsive:

npm i -D gulp gulp-sharp-responsive

Here, -i serves as shorthand for install, and -D represents --save-dev, ensuring the packages are saved as development dependencies.

Step 2: Create Input and Output Folders

Unless you already have input and output folders for your tech stack (e.g., src and public folders), create two folders inside the project directory, namely input and output.

Having separate folders for original (unoptimized) and processed (optimized) images helps organize them and easily restore the original versions should you need them in any case.

You can structure and place these folders as needed, but the gulpfile (explained in the next section) must be placed in the project's root directory.

Step 3: Create gulpfile.js

When configuring Gulp.js, you have flexibility in structuring its configuration filegulpfile.js. You can either consolidate all tasks into a single gulpfile.js or organize them into separate files and import them into a main index file.

The approach you choose depends on your preferences and level of expertise. For the sake of simplicity in this tutorial, I'll opt for the latter, creating separate JS files for each task.

Begin by creating a directory named gulpfile.js within your project's root directory. This directory will contain individual image optimization tasks or files, such as minification (or image compression) and conversion of JPEG and PNG images to WebP formats.

Within this directory, create an index.js file. This serves as the main index file where you'll import all individual tasks (JS files) and export them as gulp tasks (to run in the terminal).

In the index.js file, insert the following code:

const { optimizeJpeg } = require('./optimize-jpeg'),
  { optimizePng } = require('./optimize-png'),
  { convertToWebp } = require('./convert-to-webp');

exports.optimizeJpeg = optimizeJpeg;
exports.optimizePng = optimizePng;
exports.convertToWebp = convertToWebp;

Step 4: Create the JPEG Optimization Task

Inside the gulpfile.js directory, create an optimize-jpeg.js file.

Inside this file, add the following code:

const gulp = require('gulp'),
  sharp = require('gulp-sharp-responsive');

exports.optimizeJpeg = function optimizeJpeg() {
  return gulp
    .src('input/jpeg/**/*.{jpeg,jpg}')

    .pipe(
      sharp({
        formats: [
          {
            format: 'jpeg',

            width: 1024,

            jpegOptions: {
              quality: 80,
              progressive: true,
            },
          },
        ],
      })
    )

    .pipe(gulp.dest('output/jpeg/'));
};

To maintain focus in this tutorial, I'll only explain the options related to gulp-sharp-responsive, leaving discussions on Gulp and related topics for another article. However, you can always explore Gulp and its associated concepts on its official website.

With that said, pay attention to lines 6 and 25, where the src() and dest() Gulp methods specify the input and output paths of the files respectively.

Moving on, lines 9-22 (the sharp() function call) represent the plugin options. Let's briefly go through them now.

  • format: Determines the output image format (jpeg, in this case).
  • width: Defines the width for resizing the image (with the height adjusted proportionally based on the new width). If not applicable, use null or remove the property.
  • jpegOptions: Specifies various options for processing JPEG images, such as output quality and whether the image should be progressive.

To learn about different optimization options, refer to the relevant plugin documentation (gulp-sharp-responsive and Sharp image processor).

Step 5: Create the PNG Optimization Task

Within the gulpfile.js directory, create an optimize-png.js file.

Inside this file, add the following code:

const gulp = require('gulp'),
  sharp = require('gulp-sharp-responsive');

exports.optimizePng = function optimizePng() {
  return gulp
    .src('input/png/**/*.png')

    .pipe(
      sharp({
        formats: [
          {
            format: 'png',

            width: 1024,

            pngOptions: {
              quality: 80,
              progressive: true,
              compressionLevel: 9,
              effort: 10,
            },
          },
        ],
      })
    )
    .pipe(gulp.dest('output/png/'));
};

Step 6: Create the WebP Conversion Task

Now, let's create a task responsible for converting JPEG and PNG images into the WebP format.

Inside the gulpfile.js directory, create a convert-to-webp.js file.

Inside this file, add the following code:

const gulp = require('gulp'),
  sharp = require('gulp-sharp-responsive');

exports.convertToWebp = function convertToWebp() {
  return gulp
    .src('input/**/*.{jpeg,jpg,png}')

    .pipe(
      sharp({
        formats: [
          {
            format: 'webp',

            width: 1024,

            webpOptions: {
              quality: 80,
              effort: 6,
            },
          },
        ],
      })
    )

    .pipe(gulp.dest('output/webp/'));
};

Step 7: Run and Test the Optimization Tasks

Let's test if the scripts function correctly.

To do this, place temporary images (both JPEG and PNG) in the appropriate input folders. By default, use input/jpeg/ for JPEG images and input/png/ for PNG images.

In the terminal, execute the following commands to process the images:

For JPEG

npx gulp optimizeJpeg

For PNG

npx gulp optimizePng

For WebP

npx gulp convertToWebp

If everything runs smoothly, you should notice the relevant output messages, confirming successful optimization, similar to the following:

Starting 'optimizeJpeg'...
Finished 'optimizeJpeg' after 93 ms

Find the processed images inside the corresponding image type folder (JPEG, PNG, or WebP) within the output directory.

Step 8: Add Tasks to the package.json File

Given that you can run the tasks via CLI, it's convenient to include these tasks in your package.json file as npm run scripts. With this setup, you can effortlessly execute any Gulp tasks with a single click using the NPM Scripts section in Visual Studio Code (learn more). This helps save time and prevents errors.

To do this, open the package.json file and add the Gulp tasks inside the scripts object as follows:

{
  "scripts": {
    "optimize-jpeg": "gulp optimizeJpeg",
    "optimize-png": "gulp optimizePng",
    "convert-to-webp": "gulp convertToWebp",
  },
  "devDependencies": {
    "gulp": "^4.0.2",
    "gulp-sharp-responsive": "^0.4.1"
  }
}

Running any script from the NPM Scripts sidebar in VS Code will execute the corresponding Gulp task in the terminal.

Bonus #1: Run Tasks Simultaneously Using the parallel() Method

Running individual tasks is flexible and suitable for specific situations, but what if you want to run all tasks simultaneously? Fortunately, that's precisely what you'll implement in this bonus section.

First, open the index.js file located in the gulpfile.js directory.

In the variables section at the top, import the parallel() method using a destructuring assignment as follows:

const { optimizeJpeg } = require('./optimize-jpeg'),
  { optimizePng } = require('./optimize-png'),
  { convertToWebp } = require('./convert-to-webp'),
  { parallel } = require('gulp');

Then, add the following line at the end of the file:

exports.optimizeAll = parallel(optimizeJpeg, optimizePng, convertToWebp);

Finally, open the package.json file and add the new task in the scripts object:

"optimize-all": "gulp optimizeAll"

When run, the script will execute the optimizeAll Gulp task, which in turn will concurrently execute the individual optimization tasks (optimizeJpeg, optimizePng, and convertToWebp).

Feel free to test the script. If everything proceeds smoothly, the terminal should display the relevant success messages as shown below.

Starting 'optimizeAll'...
Starting 'optimizeJpeg'...
Starting 'optimizePng'...
Starting 'convertToWebp'...
Finished 'optimizeJpeg' after 81 ms
Finished 'optimizePng' after 125 ms
Finished 'convertToWebp' after 196 ms
Finished 'optimizeAll' after 199 ms

Bonus #2: Watch the Input Folders for Automatically Running Tasks

Manually running tasks can become tedious, especially when constantly dealing with images. In this bonus section, you'll improve the existing Gulp workflow by automating task execution whenever changes are detected in the input directories.

Thanks to Gulp's watch() method, you can set up automation to execute the necessary optimization tasks when changes occur in the input directory.

First, import the watchImg function and export it as a Gulp task in the main gulpfile as follows:

const { optimizeJpeg } = require('./optimize-jpeg'),
  { optimizePng } = require('./optimize-png'),
  { convertToWebp } = require('./convert-to-webp'),
  { parallel } = require('gulp'),
  { watchImg } = require('./watch-img');

exports.optimizeJpeg = optimizeJpeg;
exports.optimizePng = optimizePng;
exports.convertToWebp = convertToWebp;
exports.optimizeAll = parallel(optimizeJpeg, optimizePng, convertToWebp);
exports.watchImg = watchImg;

Next, inside the gulpfile.js directory, create a watch-img.js file.

Then, add the following code inside this file:

const { watch } = require('gulp'),
  { optimizeJpeg } = require('./optimize-jpeg'),
  { optimizePng } = require('./optimize-png'),
  { convertToWebp } = require('./convert-to-webp');

exports.watchImg = function watchImg() {
  watch('input/jpeg/', optimizeJpeg);
  watch('input/png/', optimizePng);
  watch('input/', convertToWebp);
};

Lastly, update the package.json file to add the new watch task as mentioned below:

"watch-img": "gulp watchImg"

Now, simply run the script once, and it will continuously monitor the input directory for any changes (by default, the input folder in the root project directory). You can monitor the script's status using the integrated terminal in VS Code.

Starting 'watchImg'...
Starting 'optimizePng'...
Starting 'convertToWebp'...
Finished 'optimizePng' after 136 ms
Finished 'convertToWebp' after 180 ms

Whenever you add, update, or remove any files inside the input directory, the watchImg function will execute the relevant tasks (PNG, JPEG, or WebP optimizations).

Wrapping Up

That concludes the tutorial for optimizing images using Gulp, which includes tasks such as minifying, scaling, and converting to the modern WebP format. While this tutorial covered the basics of both Gulp.js and the gulp-sharp-responsive plugin, there's much more to explore in their documentation, including additional features and customization options.

If you encounter any issues configuring Gulp or anything else discussed in this tutorial, don't hesitate to contact me via email at [email protected]. I'm more than happy to assist you! 🙂

Alternatively, if you prefer an already-configured Gulp image optimization solution, then Essential Gulp Kit is the perfect choice for you. It goes beyond image optimization, covering all the essential front-end development needs. 🚀

Contents

    Danial Zahid's headshot.

    About Danial Zahid

    I'm a self-taught web developer passionate about everything related to websites and web development. Over the past years, I've explored and worked with different web technologies and tools, notably WordPress, Eleventy, npm, and Gulp.js, to name a few.

    In addition, I've created and currently maintain several open-source projects, including web apps, widgets, websites, and more.

    When I'm not writing content for W3Things or doing web development work, I enjoy my free time by playing games or listening to podcasts.

    Get Essential Gulp Kit

    The ultimate Gulp.js solution to improve your developer experience.

    • Includes complete Gulp.js toolkit setup
    • Optimize website content and static assets
    • Continuous asset optimization during development phase
    • Optimize unlimited number of files in bulk
    • Plus many more awesome features

    Subscribe to the Newsletter

    This website uses cookies to optimize your site experience. By continuing to use the site, you are agreeing to its privacy policy and the use of cookies.