image-minimizer-webpack-plugin
Version:
Webpack loader and plugin to optimize (compress) images using imagemin
850 lines (679 loc) • 23.3 kB
Markdown
<!--lint disable no-html-->
<div align="center">
<a href="https://github.com/webpack/webpack">
<img width="200" height="200" hspace="10"
src="https://cdn.rawgit.com/webpack/media/e7485eb2/logo/icon.svg">
</a>
<h1>Imagemin Webpack</h1>
<p>
Plugin and Loader for <a href="http://webpack.js.org/">webpack</a> to optimize (compress) all images using <a href="https://github.com/imagemin/imagemin">imagemin</a>.
Do not worry about size of images, now they are always optimized/compressed.
</p>
</div>
<!--lint enable no-html-->
[![npm][npm]][npm-url]
[![node][node]][node-url]
[![deps][deps]][deps-url]
[![tests][tests]][tests-url]
[![cover][cover]][cover-url]
[![chat][chat]][chat-url]
[![size][size]][size-url]
# image-minimizer-webpack-plugin
This plugin uses [imagemin](https://github.com/imagemin/imagemin) to optimize your images.
## Getting Started
To begin, you'll need to install `image-minimizer-webpack-plugin`:
```console
$ npm install image-minimizer-webpack-plugin --save-dev
```
Images can be optimized in two modes:
1. [Lossless](https://en.wikipedia.org/wiki/Lossless_compression) (without loss of quality).
2. [Lossy](https://en.wikipedia.org/wiki/Lossy_compression) (with loss of quality).
Note:
- [imagemin-mozjpeg](https://github.com/imagemin/imagemin-mozjpeg) can be configured in lossless and lossy mode.
- [imagemin-svgo](https://github.com/imagemin/imagemin-svgo) can be configured in lossless and lossy mode.
Explore the options to get the best result for you.
**Recommended imagemin plugins for lossless optimization**
```shell
npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo --save-dev
```
**Recommended imagemin plugins for lossy optimization**
```shell
npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo --save-dev
```
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: 'file-loader', // Or `url-loader` or your other loader
},
],
},
],
},
plugins: [
new ImageMinimizerPlugin({
minimizerOptions: {
// Lossless optimization with custom option
// Feel free to experiment with options for better result for you
plugins: [
['gifsicle', { interlaced: true }],
['jpegtran', { progressive: true }],
['optipng', { optimizationLevel: 5 }],
[
'svgo',
{
plugins: [
{
removeViewBox: false,
},
],
},
],
],
},
}),
],
};
```
> ℹ️ Only for `4` version of `webpack`: Make sure that plugin place after any plugins that add images or other assets which you want to optimized.\*\*
> ℹ️ If you want to use `loader` or `plugin` standalone see sections below, but this is not recommended.
### Standalone Loader
[Documentation: Using loaders](https://webpack.js.org/concepts/loaders/)
In your `webpack.config.js`, add the `ImageMinimizerPlugin.loader`, chained with the [file-loader](https://github.com/webpack/file-loader) or [url-loader](https://github.com/webpack-contrib/url-loader):
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: 'file-loader', // Or `url-loader` or your other loader
},
{
loader: ImageMinimizerPlugin.loader,
options: {
severityError: 'warning', // Ignore errors on corrupted images
minimizerOptions: {
plugins: ['gifsicle'],
},
},
},
],
},
],
},
};
```
### Standalone Plugin
[Documentation: Using plugins](https://webpack.js.org/concepts/plugins/)
**webpack.config.js**
```js
const ImageminWebpack = require('image-minimizer-webpack-plugin');
module.exports = {
module: {
rules: [
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
},
test: /\.(jpe?g|png|gif|svg)$/i,
},
],
},
plugins: [
// Make sure that the plugin placed after any plugins that added images
new ImageminWebpack({
severityError: 'warning', // Ignore errors on corrupted images
minimizerOptions: {
plugins: ['gifsicle'],
},
// Disable `loader`
loader: false,
}),
],
};
```
## Options
### Plugin Options
<!--lint disable no-html-->
| Name | Type | Default | Description |
| :------------------------: | :---------------------------------------: | :---------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------ |
| **`test`** | `{String\/RegExp\|Array<String\|RegExp>}` | <code>/\.(jpe?g\|png\|gif\|tif\|webp\|svg\|avif)\$/i</code> | Test to match files against |
| **`include`** | `{String\/RegExp\|Array<String\|RegExp>}` | `undefined` | Files to `include` |
| **`exclude`** | `{String\/RegExp\|Array<String\|RegExp>}` | `undefined` | Files to `exclude` |
| **`filter`** | `{Function}` | `() => true` | Allows filtering of images for optimization |
| **`severityError`** | `{Boolean\|String}` | `'auto'` | Allows to choose how errors are displayed |
| **`minimizerOptions`** | `{Object}` | `{ plugins: [] }` | Options for `imagemin` |
| **`loader`** | `{Boolean}` | `true` | Automatically adding `imagemin-loader` (require for minification images using in `url-loader`, `svg-url-loader` or other) |
| **`maxConcurrency`** | `{Number}` | `Math.max(1, os.cpus().length - 1)` | Maximum number of concurrency optimization processes in one time |
| **`filename`** | `{string}` | `'[path][name][ext]'` | Allows to set the filename for the generated asset. Useful for converting to a `webp` |
| **`deleteOriginalAssets`** | `{Boolean}` | `false` | Allows to delete the original asset. Useful for converting to a `webp` and remove original assets |
<!--lint enable no-html-->
#### `test`
Type: `String|RegExp|Array<String|RegExp>`
Default: `/\.(jpe?g\|png\|gif\|tif\|webp\|svg\|avif)\$/i`
Test to match files against.
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
new ImageMinimizerPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
}),
],
};
```
#### `include`
Type: `String|RegExp|Array<String|RegExp>`
Default: `undefined`
Files to include.
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
new ImageMinimizerPlugin({
include: /\/includes/,
}),
],
};
```
#### `exclude`
Type: `String|RegExp|Array<String|RegExp>`
Default: `undefined`
Files to exclude.
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
new ImageMinimizerPlugin({
exclude: /\/excludes/,
}),
],
};
```
#### `filter`
Type: `Function`
Default: `() => true`
Allows filtering of images for optimization.
Return `true` to optimize the image, `false` otherwise.
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
new ImageMinimizerPlugin({
filter: (source, sourcePath) => {
// The `source` argument is a `Buffer` of source file
// The `sourcePath` argument is an absolute path to source
if (source.byteLength < 8192) {
return false;
}
return true;
},
}),
],
};
```
#### `severityError`
Type: `Boolean|String`
Default: `'auto'`
Allows to choose how errors are displayed.
Сan have the following values:
- `'auto'` - emit warnings in `development` mode and emit errors in `production` mode (default behavior)
- `false` or `'off'` - suppresses errors and warnings
- `'warning'` - emit warnings instead errors
- `true` or `'error'` - emit errors
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
new ImageMinimizerPlugin({
severityError: 'warning',
}),
],
};
```
#### `minimizerOptions`
Type: `Object`
Default: `{ plugins: [] }`
Options for [`imagemin`](https://github.com/imagemin/imagemin).
More information and examples [here](https://github.com/imagemin/imagemin).
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
new ImageMinimizerPlugin({
minimizerOptions: {
plugins: [
// Name
'gifsicle',
// Name with options
['mozjpeg', { quality: 80 }],
// Full package name
[
'imagemin-svgo',
{
plugins: [
{
removeViewBox: false,
},
],
},
],
[
// Custom package name
'nonstandard-imagemin-package-name',
{ myOptions: true },
],
],
},
}),
],
};
```
#### `loader`
Type: `Boolean`
Default: `true`
Automatically adding `imagemin-loader`.
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
new ImageMinimizerPlugin({
loader: false,
}),
],
};
```
#### `maxConcurrency`
Type: `Number`
Default: `Math.max(1, os.cpus().length - 1)`
Maximum number of concurrency optimization processes in one time.
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
new ImageMinimizerPlugin({
maxConcurrency: 3,
}),
],
};
```
#### `filename`
Type: `String`
Default: `'[path][name][ext]'`
Allows to set the filename for the generated asset. Useful for converting to a `webp`.
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
// Images are converted to `webp` and the original assets have been kept
new ImageMinimizerPlugin({
test: /\.(png)$/i,
filename: '[path][name].webp',
minimizerOptions: {
plugins: ['imagemin-webp'],
},
}),
],
};
```
#### `deleteOriginalAssets`
Type: `Boolean`
Default: `false`
Allows to remove original assets. Useful for converting to a `webp` and remove original assets
> i Doesn't make sense if you haven't changed the original value of the `filename` option
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
// Images are converted to `webp` and the original assets have been removed
new ImageMinimizerPlugin({
test: /\.(png)$/i,
deleteOriginalAssets: true,
filename: '[path][name].webp',
minimizerOptions: {
plugins: ['imagemin-webp'],
},
}),
],
};
```
To generate and compress the original assets:
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
// And the original assets will be compressed
new ImageMinimizerPlugin({
test: /\.(png)$/i,
minimizerOptions: {
plugins: ['pngquant'],
},
}),
// Images are converted to `webp` and the original assets have been removed
new ImageMinimizerPlugin({
test: /\.(png)$/i,
deleteOriginalAssets: false,
filename: '[path][name].webp',
minimizerOptions: {
plugins: ['imagemin-webp'],
},
}),
],
};
```
### Loader Options
| Name | Type | Default | Description |
| :------------------------: | :-----------------: | :-------------------: | :------------------------------------------------------------------------------------------------ |
| **`filter`** | `{Function}` | `undefined` | Allows filtering of images for optimization |
| **`severityError`** | `{Boolean\|String}` | `'auto'` | Allows to choose how errors are displayed |
| **`minimizerOptions`** | `{Object}` | `{ plugins: [] }` | Options for `imagemin` |
| **`filename`** | `{string}` | `'[path][name][ext]'` | Allows to set the filename for the generated asset. Useful for converting to a `webp` |
| **`deleteOriginalAssets`** | `{Boolean}` | `false` | Allows to delete the original asset. Useful for converting to a `webp` and remove original assets |
#### `filter`
Type: `Function`
Default: `() => true`
Allows filtering of images for optimization.
Return `true` to optimize the image, `false` otherwise.
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: 'file-loader', // Or `url-loader` or your other loader
},
{
loader: ImageMinimizerPlugin.loader,
options: {
cache: true,
filter: (source, sourcePath) => {
// The `source` argument is a `Buffer` of source file
// The `sourcePath` argument is an absolute path to source
if (source.byteLength < 8192) {
return false;
}
return true;
},
minimizerOptions: {
plugins: ['gifsicle'],
},
},
},
],
},
],
},
};
```
#### `severityError`
Type: `Boolean|String`
Default: `'auto'`
Allows to choose how errors are displayed.
Сan have the following values:
- `'auto'` - emit warnings in `development` mode and emit errors in `production` mode (default behavior)
- `false` or `'off'` - suppresses errors and warnings
- `'warning'` - emit warnings instead errors
- `true` or `'error'` - emit errors
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: 'file-loader', // Or `url-loader` or your other loader
},
{
loader: ImageMinimizerPlugin.loader,
options: {
severityError: 'warning',
minimizerOptions: {
plugins: ['gifsicle'],
},
},
},
],
},
],
},
};
```
#### `minimizerOptions`
Type: `Object`
Default: `{ plugins: [] }`
Options for `imagemin`.
Options for [`imagemin`](https://github.com/imagemin/imagemin)
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: 'file-loader', // Or `url-loader` or your other loader
},
{
loader: ImageMinimizerPlugin.loader,
options: {
severityError: 'warning',
minimizerOptions: {
plugins: [
['gifsicle', { interlaced: true, optimizationLevel: 3 }],
],
},
},
},
],
},
],
},
};
```
#### `filename`
Type: `String`
Default: `'[path][name][ext]'`
Allows to set the filename for the generated asset. Useful for converting to a `webp`.
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif)$/i,
use: [
{
loader: 'file-loader', // Or `url-loader` or your other loader
},
{
loader: ImageMinimizerPlugin.loader,
options: {
filename: '[path][name].webp',
minimizerOptions: {
plugins: ['imagemin-webp'],
},
},
},
],
},
],
},
};
```
#### `deleteOriginalAssets`
Type: `Boolean`
Default: `false`
Allows to keep the original asset. Useful for converting to a `webp` and remove original assets.
> i Doesn't make sense if you haven't changed the original value of the `filename` option
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.(png)$/i,
use: [
{
loader: 'file-loader', // Or `url-loader` or your other loader
},
{
loader: ImageMinimizerPlugin.loader,
options: {
// PNG images are converted to WEBP, and the originals will keep
deleteOriginalAssets: false,
filename: '[path][name].webp',
minimizerOptions: {
plugins: ['imagemin-webp'],
},
},
},
],
},
],
},
};
```
## Additional API
### `normalizeConfig(config)`
The function normalizes configuration (converts plugins names and options to `Function`s) for using in `imagemin` package directly.
```js
const imagemin = require('imagemin');
const { normalizeConfig } = require('image-minimizer-webpack-plugin');
const imageminConfig = normalizeConfig({
plugins: [
'jpegtran',
[
'pngquant',
{
quality: [0.6, 0.8],
},
],
],
});
/*
console.log(imageminConfig);
=>
{
plugins: [Function, Function],
pluginsMeta: [
{ name: "imagemin-jpegtran", version: "x.x.x", options: {} },
{ name: "imagemin-pngquant", version: "x.x.x", options: { quality: [0.6, 0.8] }
]
}
*/
(async () => {
const files = await imagemin(['images/*.{jpg,png}'], {
destination: 'build/images',
plugins: imageminConfig.plugins,
});
console.log(files);
// => [{data: <Buffer 89 50 4e …>, path: 'build/images/foo.jpg'}, …]
})();
```
## Examples
### Optimize images based on size
You can use difference options (like `progressive`/`interlaced` and etc) based on image size (example - don't do progressive transformation for small images).
What is `progressive` image? [`Answer here`](https://jmperezperez.com/medium-image-progressive-loading-placeholder/).
**webpack.config.js**
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
minimizer: [
new ImageMinimizerPlugin({
// Only apply this one to files equal to or over 8192 bytes
filter: (source) => {
if (source.byteLength >= 8192) {
return true;
}
return false;
},
minimizerOptions: {
plugins: [['jpegtran', { progressive: true }]],
},
}),
new ImageMinimizerPlugin({
// Only apply this one to files under 8192
filter: (source) => {
if (source.byteLength < 8192) {
return true;
}
return false;
},
minimizerOptions: {
plugins: [['jpegtran', { progressive: false }]],
},
}),
],
};
```
### Optimize and transform images to `webp`
```js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
plugins: [
new ImageMinimizerPlugin({
minimizerOptions: {
plugins: ['pngquant'],
},
}),
new ImageMinimizerPlugin({
deleteOriginalAssets: false,
filename: '[path][name].webp',
minimizerOptions: {
plugins: ['imagemin-webp'],
},
}),
],
};
```
## Contributing
Please take a moment to read our contributing guidelines if you haven't yet done so.
[CONTRIBUTING](./.github/CONTRIBUTING.md)
## License
[MIT](./LICENSE)
[npm]: https://img.shields.io/npm/v/image-minimizer-webpack-plugin.svg
[npm-url]: https://npmjs.com/package/image-minimizer-webpack-plugin
[node]: https://img.shields.io/node/v/image-minimizer-webpack-plugin.svg
[node-url]: https://nodejs.org
[deps]: https://david-dm.org/webpack-contrib/image-minimizer-webpack-plugin.svg
[deps-url]: https://david-dm.org/webpack-contrib/image-minimizer-webpack-plugin
[tests]: https://github.com/webpack-contrib/image-minimizer-webpack-plugin/workflows/image-minimizer-webpack-plugin/badge.svg
[tests-url]: https://github.com/webpack-contrib/image-minimizer-webpack-plugin/actions
[cover]: https://codecov.io/gh/webpack-contrib/image-minimizer-webpack-plugin/branch/master/graph/badge.svg
[cover-url]: https://codecov.io/gh/webpack-contrib/image-minimizer-webpack-plugin
[chat]: https://badges.gitter.im/webpack/webpack.svg
[chat-url]: https://gitter.im/webpack/webpack
[size]: https://packagephobia.now.sh/badge?p=image-minimizer-webpack-plugin
[size-url]: https://packagephobia.now.sh/result?p=image-minimizer-webpack-plugin