Using Imagemin with Webpack

Install the Imagemin Webpack plugin

This Glitch already contains webpack and webpack-cli, but you'll need to install imagemin-webpack-plugin.

  • Click the Remix This button to make the project editable.

  • Click the Status button.

  • Then click the Console button. This will open a new window.

  • Lastly, type this command into the console:
npm install --save-dev imagemin-webpack-plugin

Setup imagemin-webpack-plugin:

The existing webpack.config.js for this project has been copying images from the images/ directory to the dist/ directory but it hasn't been compressing them.

Why would you copy images to a new `dist/` folder? `dist/` is short for "distribution" and it's fairly common practice to keep original code, images, etc. separate from their distributed versions because they may be slightly different.

First, declare the Imagemin plugin by adding this code at the top of webpack.config.js:

const ImageminPlugin = require('imagemin-webpack-plugin').default;

Next, add the following code as the last item in the plugins[] array. This adds Imagemin to the list of plugins that Webpack uses:

new ImageminPlugin()
Why add it at the end of the array? Adding it there ensures that Imagemin runs last, after all the other plugins.

✔︎ Check-in

Your complete webpack.config.js file should now look like this:

const ImageminPlugin = require('imagemin-webpack-plugin').default;
const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require('path');

module.exports = {
  entry: './index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
     new CopyWebpackPlugin([{
       from: 'img/**/**',
       to: path.resolve(__dirname, 'dist')
     }]),
     new ImageminPlugin()
  ]
}

You now have a Webpack config that compresses images using Imagemin.

Run Webpack

  • In the console, run Webpack to compress your images:
webpack --config webpack.config.js --mode development

But what happens if you run Webpack in production mode?

  • Re-run Webpack, but this time in production mode:
webpack --config webpack.config.js --mode production

This time around, Webpack displays a warning letting you know that your PNG files, in spite of some compression, still exceed the recommended size limit. (Webpack's development & production modes prioritize different things, which is why you only see this warning while running Webpack in production mode.)

Customize our Imagemin configuration to fix this warning.

Customize your Imagemin Configuration

Add settings for compressing PNG images by passing the following object to ImageminPlugin():

{pngquant: ({quality: '50'})}

This code tells Webpack to compress PNGs to a quality of '50' ('0' is the worst; '100' is the best) using the Pngquant plugin.

✔︎ Check-in

Your webpack.config.js file should now look like this:

const ImageminPlugin = require('imagemin-webpack-plugin').default;
const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require('path');

module.exports = {
  entry: './index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new CopyWebpackPlugin([{
        from: 'img/**/**',
        to: path.resolve(__dirname, 'dist')
    }]),
    new ImageminPlugin({
      pngquant: ({quality: '50'}),
      })
  ]
}

But what about JPEGs? The project also has JPEG images, so you should specify how they are compressed as well.

Customize your Imagemin Configuration (continued)

Instead of using imagemin-webpack-plugin's default plugin for JPG compression (imagemin-jpegtran), use the imagemin-mozjpeg plugin. Unlike Jpegtran, Mozjpeg let's you specify a compression quality for your JPG compression.

  • Install the Mozjpeg plugin:
npm install --save-dev imagemin-mozjpeg
  • Next, initialize the imagemin-mozjpeg plugin by adding the following line at the top of your webpack.config.js file:
const imageminMozjpeg = require('imagemin-mozjpeg');
  • Add a plugins property to the object passed to ImageminPlugin(), such that the object now looks like this:
new ImageminPlugin({
  pngquant: ({quality: '50'}),
  plugins: [imageminMozjpeg({quality: '50'})]
})

This code tells Webpack to compress JPGs to a quality of '50' ('0' is the worst; '100' is the best) using the Mozjpeg plugin.

Are you wondering why Mozjpeg is added to the plugins array, but Pngquant isn't? Good question.

If you're adding settings for a plugin that is a default plugin of imagemin-webpack-plugin, they can be added as a key-object pair on the object passed to ImageminPlugin(). The settings for Pnquant are a good example of this.

However, if you're adding settings for non-default plugins (for example, Mozjpeg), they should be added by including them in the array corresponding to the plugins property.

✔︎ Check-in

Your code should now look like this:

const imageminMozjpeg = require('imagemin-mozjpeg');
const ImageminPlugin = require('imagemin-webpack-plugin').default;
const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require('path');

module.exports = {
  entry: './index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new CopyWebpackPlugin([{
      from: 'img/**/**',
      to: path.resolve(__dirname, 'dist')
    }]),
    new ImageminPlugin({
      pngquant: ({quality: '50'}),
      plugins: [imageminMozjpeg({quality: '50'})]
    })
  ]
}

Re-run Webpack & verify results with Lighthouse

  • In the console, re-run Webpack:
webpack --config webpack.config.js --mode production

Hooray! Your changes should have fixed the Webpack warnings.

Webpack warns you about large images, but it can't tell you if images are uncompressed or undercompressed. This is why it's always a good idea to use Lighthouse to verify your changes.

Lighthouse's "Efficiently encode images" performance audit can let you know if the JPEG images on your page are optimally compressed.

  • Click on the Show Live button to view the live version of the your Glitch.

Run the Lighthouse performance audit (Lighthouse > Options > Performance) on the live version of your Glitch and verify that the "Efficiently encode images" audit was passed.

Passing 'Efficiently encode images' audit in Lighthouse

Success! You have used Imagemin to optimally compress the images on your page.