![Katie Hempenius](https://web.dev/images/authors/katiehempenius.jpg) Katie Hempenius [X](https://twitter.com/katiehempenius)

<br />

> [!IMPORTANT]
> To follow this codelab, open [this Glitch](https://glitch.com/edit/#!/imagemin-webpack) in a second tab.

## Set up the Imagemin webpack plugin

This Glitch already contains `webpack`, `webpack-cli`, and
`imagemin-webpack-plugin`. To add the configuration for Imagemin, you'll need
to edit your `webpack.config.js` file.

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.

- Click **Remix to Edit** to make the project editable.

> [!NOTE]
> **Note:** 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()

> [!NOTE]
> **Note:** 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

- Click **Terminal** (note: if the Terminal button does not show you may need to use the Fullscreen option).
- To compress your images, run webpack by typing the following command into the console:

    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: [0.5, 0.5]})}

This code tells Imagemin to compress PNGs using the Pngquant plugin. The
`quality` field uses a `min` and `max` range of values to determine the
compression level---0 is the lowest and 1 is the highest. To force all images to
be compressed at 50% quality, pass `0.5` as both the min and max value.

## ✔︎ 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: [0.5, 0.5]}),
          })
      ]
    }

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. We've
already installed the Mozjpeg plugin for you in this Glitch, but you'll need to
edit your `webpack.config.js` file:

- 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: [0.5, 0.5]}),
      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.

> [!NOTE]
> **Note:** 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: [0.5, 0.5]}),
          plugins: [imageminMozjpeg({quality: 50})]
        })
      ]
    }

## Re-run webpack and 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.

- To preview the site, press **View App** . Then press **Fullscreen** ![fullscreen](https://web.dev/static/images/glitch/fullscreen.svg).
- 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](https://web.dev/static/articles/codelab-imagemin-webpack/image/passing-efficiently-enco-3ca0d565efca6.png)

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