The AutomaticPrefetchPlugin
discovers all modules from the previous compilation upfront while watching for changes, trying to improve the incremental build times. Compared to PrefetchPlugin
which discovers a single module upfront.
webpack.config.js
module.exports = {
// ...
plugins: [new webpack.AutomaticPrefetchPlugin()],
};
Adds a banner to the top of each generated chunk.
const webpack = require('webpack');
new webpack.BannerPlugin(banner);
// or
new webpack.BannerPlugin(options);
{
banner: string | function, // the banner as string or function, it will be wrapped in a comment
raw: boolean, // if true, banner will not be wrapped in a comment
entryOnly: boolean, // if true, the banner will only be added to the entry chunks
test: string | RegExp | [string, RegExp], // Include all modules that pass test assertion.
include: string | RegExp | [string, RegExp], // Include all modules matching any of these conditions.
exclude: string | RegExp | [string, RegExp], // Exclude all modules matching any of these conditions.
footer?: boolean, // if true, the banner will be placed at the end of the compilation
stage?: number, // the stage of the compilation in which the banner should be injected
}
import webpack from 'webpack';
// string
new webpack.BannerPlugin({
banner: 'hello world',
});
// function
new webpack.BannerPlugin({
banner: (yourVariable) => {
return `yourVariable: ${yourVariable}`;
},
});
// It will add the banner message after minimizers and any asset manipulation
new webpack.BannerPlugin({
raw: true,
banner: '/* banner is a string */',
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_REPORT,
});
Since webpack 2.5.0, placeholders are evaluated in the banner
string:
import webpack from 'webpack';
new webpack.BannerPlugin({
banner:
'fullhash:[fullhash], chunkhash:[chunkhash], name:[name], filebase:[filebase], query:[query], file:[file]',
});
The chunks-webpack-plugin
creates HTML files with entry points and chunks relations to serve your webpack bundles. It is suitable with multi-page applications that contain multiple entry points.
Since webpack 4, SplitChunksPlugin
offers the possibility to optimizes all chunks. It can be particularly powerful, because it means that chunks can be shared even between async and non-async chunks. See the webpack documentation of splitChunks.chunks
for details.
splitChunks.chunks
option can be set to automatically generate new chunks associated with an entry point. For example, entry points a.js
and b.js
share common code with the file vendors~a~b.js
.
With multiple entry points, it can be difficult to identify relation between the auto-generated chunks and entry points.
chunks-webpack-plugin
parses the webpack compilation entry points to get all files associated with the entry points. Then, it generates HTML files which include all assets filtered by an entry point and thechunks-manifest.json
file.
It works without configuration. For advanced usage, see the using configuration section.
chunks-webpack-plugin
is available on npm as chunks-webpack-plugin
and as chunks-webpack-plugin
on GitHub.
npm install chunks-webpack-plugin --save-dev
yarn add chunks-webpack-plugin --dev
Warning
chunks-webpack-plugin@10
is ESM only.Note Minimum supported
Node.js
version is16.20.0
and Webpack>=5.10.3
.
The project includes a minimalist example in the ./example
directory. Run the npm run build:example
command to execute the Webpack example and see the plugin's implementation in action.
chunks-webpack-plugin
will generate two HTML files for each entry point. Each filename contains the entry point name, the {{entry}}
placeholder is automatically replaced.
{{entry}}-styles.html
: contains all HTML <link>
tags{{entry}}-scripts.html
: contains all HTML <script>
tagsFirst, let's add the plugin to the webpack configuration.
webpack.config.js
import ChunksWebpackPlugin from 'chunks-webpack-plugin';
export default {
plugins: [new ChunksWebpackPlugin()]
};
HTML files are built in the output path directory with the rest of the webpack compilation.
Now you can include the generated HTML files into your HTML page templates. You can do it with e.g. Twig.
main-styles.html
<link rel="stylesheet" href="main.css" />
main-scripts.html
<script defer src="main.js"></script>
You can pass a configuration object to chunks-webpack-plugin
to override the default settings.
filename
Type:
type filename = string;
Default: '[name]-[type].html'
Tells the plugin whether to personalize the filename of the generated files. Files are processed by the webpack compilation and generated in the output path directory. The placeholder [name]
is automatically replaced by entry points names and [type]
by styles|scripts
.
new ChunksWebpackPlugin({
filename: 'templates/[name]-[type].html'
});
Note The
filename
can contain directories, which will be created automatically.
templateStyle
Type:
type templateStyle = (name: string, entryName: string) => string;
Default:
(name) => `<link rel="stylesheet" href="${name}" />`;
Tells the plugin whether to personalize the default template for the HTML <style>
tags. For example, add additional attributes or a CDN prefix.
export default {
plugins: [
new ChunksWebpackPlugin({
templateStyle: (name) => `<link rel="stylesheet" href="https://cdn.domain.com${name}" />`
})
]
};
templateScript
Type:
type templateScript = (name: string, entryName: string) => string;
Default:
(name) => `<script defer src="${name}"></script>`;
Tells the plugin whether to personalize the default template for the HTML <script>
tags. For example, add additional attributes or a CDN prefix.
export default {
plugins: [
new ChunksWebpackPlugin({
templateScript: (name) => `<script defer src="https://cdn.domain.com${name}"></script>`
})
]
};
generateChunksManifest
Type:
type generateChunksManifest = boolean;
Default: false
Tells the plugin whether to generate the chunks-manifest.json
. The file contains the list of all chunks grouped by entry points. See the chunks-manifest.json example.
export default {
plugins: [
new ChunksWebpackPlugin({
generateChunksManifest: true
})
]
};
generateChunksFiles
Type:
type generateChunksFiles = boolean;
Default: true
Tells the plugin whether to generate the HTML files.
export default {
plugins: [
new ChunksWebpackPlugin({
generateChunksFiles: false
})
]
};
Warning When set to
false
, HTML files will not be generated. It can only be useful together withgenerateChunksManifest
option set totrue
for custom generation of the HTML files.
Example of the webpack configuration with multiple entry points which share common code with the splitChunks
option.
import ChunksWebpackPlugin from 'chunks-webpack-plugin';
import path from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
entry: {
home: 'home.js',
news: 'news.js'
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist')
},
plugins: [new ChunksWebpackPlugin()],
optimization: {
splitChunks: {
chunks: 'all'
}
}
};
The plugin will generate all files in the output path directory:
home-styles.html
<link rel="stylesheet" href="vendors~home~news.css" />
<link rel="stylesheet" href="home.css" />
home-scripts.html
<script defer src="vendors~home~news.js"></script>
<script defer src="home.js"></script>
news-styles.html
<link rel="stylesheet" href="vendors~home~news.css" />
<link rel="stylesheet" href="news.css" />
news-scripts.html
<script defer src="vendors~home~news.js"></script>
<script defer src="news.js"></script>
chunks-webpack-plugin
is licensed under the MIT License.
Created with ♥ by @yoriiis.
The CommonsChunkPlugin
is an opt-in feature that creates a separate file (known as a chunk), consisting of common modules shared between multiple entry points.
By separating common modules from bundles, the resulting chunked file can be loaded once initially, and stored in cache for later use. This results in page speed optimizations as the browser can quickly serve the shared code from cache, rather than being forced to load a larger bundle whenever a new page is visited.
new webpack.optimize.CommonsChunkPlugin(options);
{
name: string, // or
names: string[],
// The chunk name of the commons chunk. An existing chunk can be selected by passing a name of an existing chunk.
// If an array of strings is passed this is equal to invoking the plugin multiple times for each chunk name.
// If omitted and `options.async` or `options.children` is set all chunks are used, otherwise `options.filename`
// is used as chunk name.
// When using `options.async` to create common chunks from other async chunks you must specify an entry-point
// chunk name here instead of omitting the `option.name`.
filename: string,
// The filename template for the commons chunk. Can contain the same placeholders as `output.filename`.
// If omitted the original filename is not modified (usually `output.filename` or `output.chunkFilename`).
// This option is not permitted if you're using `options.async` as well, see below for more details.
minChunks: number|Infinity|function(module, count) => boolean,
// The minimum number of chunks which need to contain a module before it's moved into the commons chunk.
// The number must be greater than or equal 2 and lower than or equal to the number of chunks.
// Passing `Infinity` creates the commons chunk, but moves no modules into it.
// By providing a `function` you can add custom logic. (Defaults to the number of chunks)
chunks: string[],
// Select the source chunks by chunk names. The chunk must be a child of the commons chunk.
// If omitted all entry chunks are selected.
children: boolean,
// If `true` all children of the commons chunk are selected
deepChildren: boolean,
// If `true` all descendants of the commons chunk are selected
async: boolean|string,
// If `true` a new async commons chunk is created as child of `options.name` and sibling of `options.chunks`.
// It is loaded in parallel with `options.chunks`.
// Instead of using `option.filename`, it is possible to change the name of the output file by providing
// the desired string here instead of `true`.
minSize: number,
// Minimum size of all common module before a commons chunk is created.
}
Generate an extra chunk, which contains common modules shared between entry points.
new webpack.optimize.CommonsChunkPlugin({
name: 'commons',
// (the commons chunk name)
filename: 'commons.js',
// (the filename of the commons chunk)
// minChunks: 3,
// (Modules must be shared between 3 entries)
// chunks: ["pageA", "pageB"],
// (Only use these entries)
});
You must load the generated chunk before the entry point:
<script src="commons.js" charset="utf-8"></script>
<script src="entry.bundle.js" charset="utf-8"></script>
Split your code into vendor and application.
module.exports = {
//...
entry: {
vendor: ['jquery', 'other-lib'],
app: './entry',
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
// filename: "vendor.js"
// (Give the chunk a different name)
minChunks: Infinity,
// (with more entries, this ensures that no other module
// goes into the vendor chunk)
}),
],
};
<script src="vendor.js" charset="utf-8"></script>
<script src="app.js" charset="utf-8"></script>
With Code Splitting, multiple child chunks of an entry chunk can have common dependencies. To prevent duplication these can be moved into the parent. This reduces overall size, but does have a negative effect on the initial load time. If it is expected that users will need to download many sibling chunks, i.e. children of the entry chunk, then this should improve load time overall.
new webpack.optimize.CommonsChunkPlugin({
// names: ["app", "subPageA"]
// (choose the chunks, or omit for all chunks)
children: true,
// (select all children of chosen chunks)
// minChunks: 3,
// (3 children must share the module before it's moved)
});
Similar to the above one, but instead of moving common modules into the parent (which increases initial load time) a new async-loaded additional commons chunk is used. This is automatically downloaded in parallel when the additional chunk is downloaded.
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
// or
names: ['app', 'subPageA'],
// the name or list of names must match the name or names
// of the entry points that create the async chunks
children: true,
// (use all children of the chunk)
async: true,
// (create an async commons chunk)
minChunks: 3,
// (3 children must share the module before it's separated)
});
minChunks
property a functionYou also have the ability to pass the minChunks
property a function. This function is called by the CommonsChunkPlugin
and calls the function with module
and count
arguments.
The module
argument represents each module in the chunks you have provided via the name
/names
property.
module
has the shape of a NormalModule, which has two particularly useful properties for this use case:
module.context
: The directory that stores the file. For example: '/my_project/node_modules/example-dependency'
module.resource
: The name of the file being processed. For example: '/my_project/node_modules/example-dependency/index.js'
The count
argument represents how many chunks the module
is used in.
This option is useful when you want to have fine-grained control over how the CommonsChunk algorithm determines where modules should be moved to.
new webpack.optimize.CommonsChunkPlugin({
name: 'my-single-lib-chunk',
filename: 'my-single-lib-chunk.js',
minChunks: function (module, count) {
// If module has a path, and inside of the path exists the name "somelib",
// and it is used in 3 separate chunks/entries, then break it out into
// a separate chunk with chunk keyname "my-single-lib-chunk", and filename "my-single-lib-chunk.js"
return module.resource && /somelib/.test(module.resource) && count === 3;
},
});
As seen above, this example allows you to move only one lib to a separate file if and only if all conditions are met inside the function.
This concept may be used to obtain implicit common vendor chunks:
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
// this assumes your vendor imports exist in the node_modules directory
return module.context && module.context.includes('node_modules');
},
});
To extract the webpack bootstrap logic into a separate file, use the CommonsChunkPlugin
on a name
which is not defined as entry
. Commonly the name manifest
is used. See the caching guide for details.
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity,
});
Since the vendor
and manifest
chunk use a different definition for minChunks
, you need to invoke the plugin twice:
[
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
return module.context && module.context.includes('node_modules');
},
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity,
}),
];
Prepare compressed versions of assets to serve them with Content-Encoding.
To begin, you'll need to install compression-webpack-plugin
:
npm install compression-webpack-plugin --save-dev
or
yarn add -D compression-webpack-plugin
or
pnpm add -D compression-webpack-plugin
Then add the plugin to your webpack
config. For example:
webpack.config.js
const CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
plugins: [new CompressionPlugin()],
};
And run webpack
via your preferred method.
test
Type:
type test = string | RegExp | Array<string | RegExp>;
Default: undefined
Include all assets that pass test assertion.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
test: /\.js(\?.*)?$/i,
}),
],
};
include
Type:
type include = string | RegExp | Array<string | RegExp>;
Default: undefined
Include all assets matching any of these conditions.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
include: /\/includes/,
}),
],
};
exclude
Type:
type exclude = string | RegExp | Array<string | RegExp>;
Default: undefined
Exclude all assets matching any of these conditions.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
exclude: /\/excludes/,
}),
],
};
algorithm
Type:
type algorithm =
| string
| ((
input: Buffer,
options: CompressionOptions,
callback: (
error: Error | null | undefined,
result:
| string
| ArrayBuffer
| SharedArrayBuffer
| Uint8Array
| readonly number[]
| {
valueOf(): ArrayBuffer | SharedArrayBuffer;
}
| {
valueOf(): string | Uint8Array | readonly number[];
}
| {
valueOf(): string;
}
| {
[Symbol.toPrimitive](hint:%20%22string%22): string;
},
) => void,
) => any);
Default: gzip
The compression algorithm/function.
[!NOTE]
If you use custom function for the
algorithm
option, the default value of thecompressionOptions
option is{}
.
string
The algorithm is taken from zlib.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
algorithm: "gzip",
}),
],
};
function
Allow to specify a custom compression function.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
algorithm(input, compressionOptions, callback) {
return compressionFunction(input, compressionOptions, callback);
},
}),
],
};
compressionOptions
Type:
type compressionOptions = {
flush?: number;
finishFlush?: number;
chunkSize?: number;
windowBits?: number;
level?: number;
memLevel?: number;
strategy?: number;
dictionary?: Buffer | TypedArray | DataView | ArrayBuffer;
info?: boolean;
maxOutputLength?: number;
};
Default: { level: 9 }
Compression options for algorithm
.
You can find all options here zlib.
[!NOTE]
If you use custom function for the
algorithm
option, the default value is{}
.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
compressionOptions: { level: 1 },
}),
],
};
threshold
Type:
type threshold = number;
Default: 0
Only assets bigger than this size are processed. In bytes.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
threshold: 8192,
}),
],
};
minRatio
Type:
type minRatio = number;
Default: 0.8
Only assets that compress better than this ratio are processed (minRatio = Compressed Size / Original Size
).
Example: you have image.png
file with 1024b size, compressed version of file has 768b size, so minRatio
equal 0.75
.
In other words assets will be processed when the Compressed Size / Original Size
value less minRatio
value.
You can use 1
value to process assets that are smaller than the original.
Use a value of Infinity
to process all assets even if they are larger than the original size or their original size is 0
bytes (useful when you are pre-zipping all assets for AWS).
Use a value of Number.MAX_SAFE_INTEGER
to process all assets even if they are larger than the original size, excluding assets with their original size is 0
bytes.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
// Compress all assets, including files with `0` bytes size
// minRatio: Infinity
// Compress all assets, excluding files with `0` bytes size
// minRatio: Number.MAX_SAFE_INTEGER
minRatio: 0.8,
}),
],
};
filename
Type:
type filename = string | ((pathdata: PathData) => string);
Default: "[path][base].gz"
The target asset filename.
string
For example we have assets/images/image.png?foo=bar#hash
:
[path]
is replaced with the directories to the original asset, included trailing /
(assets/images/
).
[file]
is replaced with the path of original asset (assets/images/image.png
).
[base]
is replaced with the base ([name]
+ [ext]
) of the original asset (image.png
).
[name]
is replaced with the name of the original asset (image
).
[ext]
is replaced with the extension of the original asset, included .
(.png
).
[query]
is replaced with the query of the original asset, included ?
(?foo=bar
).
[fragment]
is replaced with the fragment (in the concept of URL it is called hash
) of the original asset (#hash
).
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
filename: "[path][base].gz",
}),
],
};
function
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
filename(pathData) {
// The `pathData` argument contains all placeholders - `path`/`name`/`ext`/etc
// Available properties described above, for the `String` notation
if (/\.svg$/.test(pathData.filename)) {
return "assets/svg/[path][base].gz";
}
return "assets/js/[path][base].gz";
},
}),
],
};
deleteOriginalAssets
Type:
type deleteOriginalAssets =
| boolean
| "keep-source-map"
| ((name: string) => boolean);
Default: false
Whether to delete the original assets or not.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
deleteOriginalAssets: true,
}),
],
};
To exclude sourcemaps from compression:
module.exports = {
plugins: [
new CompressionPlugin({
exclude: /.map$/,
deleteOriginalAssets: "keep-source-map",
}),
],
};
Using a custom function:
module.exports = {
plugins: [
new CompressionPlugin({
exclude: /.map$/,
deleteOriginalAssets: (name) => {
if (/\.js$/.test(name)) {
return false;
}
return true;
},
}),
],
};
Prepare compressed versions of assets using zopfli
library.
[!NOTE]
@gfx/zopfli
require minimum8
version ofnode
.
To begin, you'll need to install @gfx/zopfli
:
$ npm install @gfx/zopfli --save-dev
webpack.config.js
const zopfli = require("@gfx/zopfli");
module.exports = {
plugins: [
new CompressionPlugin({
compressionOptions: {
numiterations: 15,
},
algorithm(input, compressionOptions, callback) {
return zopfli.gzip(input, compressionOptions, callback);
},
}),
],
};
Brotli is a compression algorithm originally developed by Google, and offers compression superior to gzip.
Node 10.16.0 and later has native support for Brotli compression in its zlib module.
We can take advantage of this built-in support for Brotli in Node 10.16.0 and later by just passing in the appropriate algorithm
to the CompressionPlugin:
webpack.config.js
const zlib = require("zlib");
module.exports = {
plugins: [
new CompressionPlugin({
filename: "[path][base].br",
algorithm: "brotliCompress",
test: /\.(js|css|html|svg)$/,
compressionOptions: {
params: {
[zlib.constants.BROTLI_PARAM_QUALITY]: 11,
},
},
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: false,
}),
],
};
[!NOTE] Brotli’s BROTLI_PARAM_QUALITY
option is functionally equivalent to zlib’s level
option.
You can find all Brotli’s options in the relevant part of the zlib module documentation.
webpack.config.js
const zlib = require("zlib");
module.exports = {
plugins: [
new CompressionPlugin({
filename: "[path][base].gz",
algorithm: "gzip",
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
}),
new CompressionPlugin({
filename: "[path][base].br",
algorithm: "brotliCompress",
test: /\.(js|css|html|svg)$/,
compressionOptions: {
params: {
[zlib.constants.BROTLI_PARAM_QUALITY]: 11,
},
},
threshold: 10240,
minRatio: 0.8,
}),
],
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
Context refers to a require with an expression such as require('./locale/' + name + '.json')
.
The ContextExclusionPlugin
allows you to exclude context. Provide RegExp as an argument when initializing the Plugin to exclude all context that matches it.
webpack.config.js
module.exports = {
plugins: [new webpack.ContextExclusionPlugin(/dont/)],
};
Context refers to a require with an expression such as require('./locale/' + name + '.json')
. When encountering such an expression, webpack infers the directory ('./locale/'
) and a regular expression (/^.*\.json$/
). Since the name
is not known at compile time, webpack includes every file as module in the bundle.
The ContextReplacementPlugin
allows you to override the inferred information. There are various ways to configure the plugin:
new webpack.ContextReplacementPlugin(
resourceRegExp: RegExp,
newContentResource?: string,
newContentRecursive?: boolean,
newContentRegExp?: RegExp
)
If the resource (directory) matches resourceRegExp
, the plugin replaces the default resource, recursive flag or generated regular expression with newContentResource
, newContentRecursive
or newContextRegExp
respectively. If newContentResource
is relative, it is resolved relative to the previous resource.
Here's a small example to restrict module usage:
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /de|fr|hu/);
The moment/locale
context is restricted to files matching /de|fr|hu/
. Thus only those locales are included (see this issue for more information).
new webpack.ContextReplacementPlugin(
resourceRegExp: RegExp,
newContentCallback: (data) => void
);
The newContentCallback
function is given a data
object of the ContextModuleFactory
and is expected to overwrite the request
attribute of the supplied object.
Using this callback we can dynamically redirect requests to a new location:
new webpack.ContextReplacementPlugin(/^\.\/locale$/, (context) => {
if (!/\/moment\//.test(context.context)) return;
Object.assign(context, {
regExp: /^\.\/\w+/,
request: '../../locale', // resolved relatively
});
});
The newContentResource
and newContentCreateContextMap
parameters are also available:
new webpack.ContextReplacementPlugin(
resourceRegExp: RegExp,
newContentResource: string,
newContentCreateContextMap: object // mapping runtime-request (userRequest) to compile-time-request (request)
);
These two parameters can be used together to redirect requests in a more targeted way. The newContentCreateContextMap
allows you to map runtime requests to compile requests in the form of an object:
new ContextReplacementPlugin(/selector/, './folder', {
'./request': './request',
'./other-request': './new-request',
});
Copies individual files or entire directories, which already exist, to the build directory.
To begin, you'll need to install copy-webpack-plugin
:
npm install copy-webpack-plugin --save-dev
or
yarn add -D copy-webpack-plugin
or
pnpm add -D copy-webpack-plugin
Then add the plugin to your webpack
config. For example:
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
{ from: "other", to: "public" },
],
}),
],
};
[!NOTE]
copy-webpack-plugin
is not designed to copy files generated from the build process; rather, it is to copy files that already exist in the source tree, as part of the build process.
[!NOTE]
If you want
webpack-dev-server
to write files to the output directory during development, you can force it with thewriteToDisk
option or thewrite-file-webpack-plugin
.
[!NOTE]
You can get the original source filename from Asset Objects.
The plugin's signature:
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
"path/to/source", // absolute or relative, files/directories/globs - see below for examples
],
options: {
concurrency: 100,
},
}),
],
};
Patterns
from
to
context
globOptions
filter
toType
force
priority
transform
transformAll
noErrorOnMissing
info
from
Type:
type from = string;
Default: undefined
Glob or path from where we copy files.
Globs accept fast-glob pattern-syntax.
Glob can only be a string
.
[!WARNING]
Don't use directly
\\
infrom
option if it is aglob
(i.epath\to\file.ext
) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/
.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
"relative/path/to/file.ext",
"relative/path/to/dir",
path.resolve(__dirname, "src", "file.ext"),
path.resolve(__dirname, "src", "dir"),
"**/*",
{
from: "**/*",
},
// If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`
path.posix.join(
path.resolve(__dirname, "src").replace(/\\/g, "/"),
"*.txt",
),
],
}),
],
};
For windows
If you define from
as absolute file path or absolute folder path on Windows
, you can use windows path segment (\\
)
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, "file.txt"),
},
],
}),
],
};
But you should always use forward-slashes in glob
expressions
See fast-glob manual.
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
// If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`
from: path.posix.join(
path.resolve(__dirname, "fixtures").replace(/\\/g, "/"),
"*.txt",
),
},
],
}),
],
};
The context
behaves differently depending on what the from
is (glob
, file
or dir
).
More examples
to
Type:
type to =
| string
| ((pathData: { context: string; absoluteFilename?: string }) => string);
Default: compiler.options.output
string
Output path.
[!WARNING]
Don't use directly
\\
into
(i.epath\to\dest
) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/
orpath
methods.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "**/*",
to: "relative/path/to/dest/",
},
{
from: "**/*",
to: "/absolute/path/to/dest/",
},
{
from: "**/*",
to: "[path][name].[contenthash][ext]",
},
],
}),
],
};
function
Allows to modify the writing path.
[!WARNING]
Don't return directly
\\
into
(i.epath\to\newFile
) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/
orpath
methods.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to({ context, absoluteFilename }) {
return "dest/newPath/[name][ext]";
},
},
],
}),
],
};
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to({ context, absoluteFilename }) {
return Promise.resolve("dest/newPath/[name][ext]");
},
},
],
}),
],
};
context
Type:
type context = string;
Default: options.context|compiler.options.context
A path to be (1) prepended to from
and (2) removed from the start of the result path(s).
[!WARNING]
Don't use directly
\\
incontext
(i.epath\to\context
) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/
orpath
methods.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.txt",
to: "dest/",
context: "app/",
},
],
}),
],
};
context
can be an absolute path or a relative path. If it is a relative path, then it will be converted to an absolute path based on compiler.options.context
.
context
should be explicitly set only when from
contains a glob. Otherwise, context
is automatically set, based on whether from
is a file or a directory:
If from
is a file, then context
is its directory. The result path will be the filename alone.
If from
is a directory, then context
equals from
. The result paths will be the paths of the directory's contents (including nested contents), relative to the directory.
The use of context
is illustrated by these examples
.
globOptions
[!WARNING]
The onlyDirectories does not work because the plugin is designed to copy files.
Type:
type globOptions = import("globby").Options;
Default: undefined
Allows to configure the glob pattern matching library used by the plugin. See the list of supported options To exclude files from the selection, you should use globOptions.ignore option
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "public/**/*",
globOptions: {
dot: true,
gitignore: true,
ignore: ["**/file.*", "**/ignored-directory/**"],
},
},
],
}),
],
};
filter
Type:
type filter = (filepath: string) => boolean;
Default: undefined
[!NOTE]
To ignore files by path please use the
globOptions.ignore
option.
webpack.config.js
const fs = require("fs").promise;
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "public/**/*",
filter: async (resourcePath) => {
const data = await fs.promises.readFile(resourcePath);
const content = data.toString();
if (content === "my-custom-content") {
return false;
}
return true;
},
},
],
}),
],
};
toType
Type:
type toType = "dir" | "file" | "template";
Default: undefined
Determinate what is to
option - directory, file or template.
Sometimes it is hard to say what is to
, example path/to/dir-with.ext
.
If you want to copy files in directory you need use dir
option.
We try to automatically determine the type
so you most likely do not need this option.
Name | Type | Default | Description |
---|---|---|---|
'dir' | string | undefined | If to has no extension or ends on '/' |
'file' | string | undefined | If to is not a directory and is not a template |
'template' | string | undefined | If to contains a template pattern |
'dir'
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "path/to/file.txt",
to: "directory/with/extension.ext",
toType: "dir",
},
],
}),
],
};
'file'
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "path/to/file.txt",
to: "file/without/extension",
toType: "file",
},
],
}),
],
};
'template'
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/",
to: "dest/[name].[contenthash][ext]",
toType: "template",
},
],
}),
],
};
force
Type:
type force = boolean;
Default: false
Overwrites files already in compilation.assets
(usually added by other plugins/loaders).
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/**/*",
to: "dest/",
force: true,
},
],
}),
],
};
priority
Type:
type priority = number;
Default: 0
Allows to specify the priority of copying files with the same destination name.
Files for patterns with higher priority will be copied later.
To overwrite files, the force
option must be enabled.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
// Copied second and will overwrite "dir_2/file.txt"
{
from: "dir_1/file.txt",
to: "newfile.txt",
force: true,
priority: 10,
},
// Copied first
{
from: "dir_2/file.txt",
to: "newfile.txt",
priority: 5,
},
],
}),
],
};
transform
Type:
type transform =
| {
transformer: (input: string, absoluteFilename: string) => string | Buffer;
cache?: boolean | TransformerCacheObject | undefined;
}
| ((input: string, absoluteFilename: string) => string | Buffer);
Default: undefined
Allows to modify the file contents.
function
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
// The `content` argument is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
// The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied
transform(content, absoluteFrom) {
return optimize(content);
},
},
],
}),
],
};
object
Name | Default | Description |
---|---|---|
transformer | undefined | Allows to modify the file contents. |
cache | false | Enable transform caching. You can use transform: { cache: { key: 'my-cache-key' } } to invalidate the cache. |
transformer
Type:
type transformer = (input: string, absoluteFilename: string) => string;
Default: undefined
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
// The `content` argument is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
// The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied
transform: {
transformer(content, absoluteFrom) {
return optimize(content);
},
},
},
],
}),
],
};
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform: {
transformer(content, path) {
return Promise.resolve(optimize(content));
},
},
},
],
}),
],
};
cache
Type:
type cache =
| boolean
| {
keys: {
[key: string]: any;
};
}
| {
keys: (
defaultCacheKeys: {
[key: string]: any;
},
absoluteFilename: string,
) => Promise<{
[key: string]: any;
}>;
}
| undefined;
Default: false
webpack.config.js
Enable/disable and configure caching.
Default path to cache directory: node_modules/.cache/copy-webpack-plugin
.
boolean
Enables/Disable transform
caching.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform: {
transformer(content, path) {
return optimize(content);
},
cache: true,
},
},
],
}),
],
};
object
Enables transform
caching and setup invalidation keys.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform: {
transformer(content, path) {
return optimize(content);
},
cache: {
keys: {
// May be useful for invalidating cache based on external values
// For example, you can invalid cache based on `process.version` - { node: process.version }
key: "value",
},
},
},
},
],
}),
],
};
You can setup invalidation keys using a function.
Simple function:
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform: {
transformer(content, path) {
return optimize(content);
},
cache: {
keys: (defaultCacheKeys, absoluteFrom) => {
const keys = getCustomCacheInvalidationKeysSync();
return {
...defaultCacheKeys,
keys,
};
},
},
},
},
],
}),
],
};
Async function:
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform: {
transformer(content, path) {
return optimize(content);
},
cache: {
keys: async (defaultCacheKeys, absoluteFrom) => {
const keys = await getCustomCacheInvalidationKeysAsync();
return {
...defaultCacheKeys,
keys,
};
},
},
},
},
],
}),
],
};
transformAll
Type:
type transformAll = (
data: {
data: Buffer;
sourceFilename: string;
absoluteFilename: string;
}[],
) => any;
Default: undefined
Allows you to modify the contents of multiple files and save the result to one file.
[!NOTE]
The
to
option must be specified and point to a file. It is allowed to use only[contenthash]
and[fullhash]
template strings.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/**/*.txt",
to: "dest/file.txt",
// The `assets` argument is an assets array for the pattern.from ("src/**/*.txt")
transformAll(assets) {
const result = assets.reduce((accumulator, asset) => {
// The asset content can be obtained from `asset.source` using `source` method.
// The asset content is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
const content = asset.data;
accumulator = `${accumulator}${content}\n`;
return accumulator;
}, "");
return result;
},
},
],
}),
],
};
noErrorOnMissing
Type:
type noErrorOnMissing = boolean;
Default: false
Doesn't generate an error on missing file(s).
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, "missing-file.txt"),
noErrorOnMissing: true,
},
],
}),
],
};
info
Type:
type info =
| Record<string, any>
| ((item: {
absoluteFilename: string;
sourceFilename: string;
filename: string;
toType: ToType;
}) => Record<string, any>);
Default: undefined
Allows to add assets info.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
"relative/path/to/file.ext",
{
from: "**/*",
// Terser skip this file for minimization
info: { minimized: true },
},
],
}),
],
};
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
"relative/path/to/file.ext",
{
from: "**/*",
// Terser skip this file for minimization
info: (file) => ({ minimized: true }),
},
],
}),
],
};
concurrency
type:
type concurrency = number;
default: 100
limits the number of simultaneous requests to fs
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [...patterns],
options: { concurrency: 50 },
}),
],
};
from
(glob
, file
or dir
).Take for example the following file structure:
src/directory-nested/deep-nested/deepnested-file.txt
src/directory-nested/nested-file.txt
Everything that you specify in from
will be included in the result:
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/directory-nested/**/*",
},
],
}),
],
};
Result:
src/directory-nested/deep-nested/deepnested-file.txt,
src/directory-nested/nested-file.txt
If you don't want the result paths to start with src/directory-nested/
, then you should move src/directory-nested/
to context
, such that only the glob pattern **/*
remains in from
:
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "**/*",
context: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
};
Result:
deep-nested/deepnested-file.txt,
nested-file.txt
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
};
Result:
deep-nested/deepnested-file.txt,
nested-file.txt
Technically, this is **/*
with a predefined context equal to the specified directory.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "**/*",
context: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
};
Result:
deep-nested/deepnested-file.txt,
nested-file.txt
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(
__dirname,
"src",
"directory-nested",
"nested-file.txt",
),
},
],
}),
],
};
Result:
nested-file.txt
Technically, this is a filename with a predefined context equal to path.dirname(pathToFile)
.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "nested-file.txt",
context: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
};
Result:
nested-file.txt
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.posix.join(
path.resolve(__dirname, "src").replace(/\\/g, "/"),
"**/*",
),
globOptions: {
ignore: [
// Ignore all `txt` files
"**/*.txt",
// Ignore all files in all subdirectories
"**/subdir/**",
],
},
},
],
}),
],
};
Removes all directory references and only copies file names.
[!WARNING]
If files have the same name, the result is non-deterministic.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/**/*",
to: "[name][ext]",
},
],
}),
],
};
Result:
file-1.txt
file-2.txt
nested-file.txt
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
// When copying files starting with a dot, must specify the toType option
// toType: "file",
to({ context, absoluteFilename }) {
return `newdirectory/${path.relative(context, absoluteFilename)}`;
},
from: "directory",
},
],
}),
],
};
Result:
"newdirectory/file-1.txt",
"newdirectory/nestedfile.txt",
"newdirectory/nested/deep-nested/deepnested.txt",
"newdirectory/nested/nestedfile.txt",
Useful if you need to simply copy *.js
files to destination "as is" without evaluating and minimizing them using Terser.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
"relative/path/to/file.ext",
{
from: "**/*",
// Terser skip this file for minimization
info: { minimized: true },
},
],
}),
],
};
yarn workspaces
and monorepos
When using yarn workspaces
or monorepos
, relative copy paths from node_modules can be broken due to the way packages are hoisting.
To avoid this, should explicitly specify where to copy the files from using require.resolve
.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: `${path.dirname(
require.resolve(`${moduleName}/package.json`),
)}/target`,
to: "target",
},
],
}),
],
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
This plugin uses cssnano to optimize and minify your CSS.
Just like optimize-css-assets-webpack-plugin but more accurate with source maps and assets using query string, allows caching and works in parallel mode.
To begin, you'll need to install css-minimizer-webpack-plugin
:
npm install css-minimizer-webpack-plugin --save-dev
or
yarn add -D css-minimizer-webpack-plugin
or
pnpm add -D css-minimizer-webpack-plugin
Then add the plugin to your webpack
configuration. For example:
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /.s?css$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
optimization: {
minimizer: [
// For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
// `...`,
new CssMinimizerPlugin(),
],
},
plugins: [new MiniCssExtractPlugin()],
};
This will enable CSS optimization only in production mode.
If you want to run it also in development set the optimization.minimize
option to true
:
webpack.config.js
// [...]
module.exports = {
optimization: {
// [...]
minimize: true,
},
};
And run webpack
via your preferred method.
Works only with source-map
, inline-source-map
, hidden-source-map
and nosources-source-map
values for the devtool
option.
Why? Because CSS support only these source map types.
The plugin respect the devtool
and using the SourceMapDevToolPlugin
plugin.
Using supported devtool
values enable source map generation.
Using SourceMapDevToolPlugin
with enabled the columns
option enables source map generation.
Use source maps to map error message locations to modules (this slows down the compilation).
If you use your own minify
function please read the minify
section for handling source maps correctly.
Name | Type | Default | Description |
---|---|---|---|
test | String|RegExp|Array<String|RegExp> | /\.css(\?.*)?$/i | 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. |
parallel | Boolean|Number | true | Enable/disable multi-process parallel running. |
minify | Function|Array<Function> | CssMinimizerPlugin.cssnanoMinify | Allows to override default minify function. |
minimizerOptions | Object|Array<Object> | { preset: 'default' } | Cssnano optimisations options. |
warningsFilter | Function<(warning, file, source) -> Boolean> | () => true | Allow to filter css-minimizer warnings. |
test
Type: String|RegExp|Array<String|RegExp>
- default: /\.css(\?.*)?$/i
Test to match files against.
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
test: /\.foo\.css$/i,
}),
],
},
};
include
Type: String|RegExp|Array<String|RegExp>
Default: undefined
Files to include.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
include: /\/includes/,
}),
],
},
};
exclude
Type: String|RegExp|Array<String|RegExp>
Default: undefined
Files to exclude.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
exclude: /\/excludes/,
}),
],
},
};
parallel
Type: Boolean|Number
Default: true
Use multi-process parallel running to improve the build speed.
Default number of concurrent runs: os.cpus().length - 1
.
ℹ️ Parallelization can speed up your build significantly and is therefore highly recommended. If a parallelization is enabled, the packages in
minimizerOptions
must be required via strings (packageName
orrequire.resolve(packageName)
). Read more inminimizerOptions
Boolean
Enable/disable multi-process parallel running.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
parallel: true,
}),
],
},
};
Number
Enable multi-process parallel running and set number of concurrent runs.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
parallel: 4,
}),
],
},
};
minify
Type: Function|Array<Function>
Default: CssMinimizerPlugin.cssnanoMinify
Allows overriding default minify function. By default, plugin uses cssnano package. Useful for using and testing unpublished versions or forks.
Possible options:
CssMinimizerPlugin.cssnanoMinify
CssMinimizerPlugin.cssoMinify
CssMinimizerPlugin.cleanCssMinify
CssMinimizerPlugin.esbuildMinify
CssMinimizerPlugin.lightningCssMinify
(previouslyCssMinimizerPlugin.parcelCssMinify
, the package was renamed, but we keep it for backward compatibility)async (data, inputMap, minimizerOptions) => {return {code: "a{color: red}", map: "...", warnings: [], errors: []}}
[!WARNING]
Always use
require
insideminify
function whenparallel
option enabled.
Function
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
level: {
1: {
roundingPrecision: "all=3,px=5",
},
},
},
minify: CssMinimizerPlugin.cleanCssMinify,
}),
],
},
};
Array
If an array of functions is passed to the minify
option, the minimizerOptions
must also be an array.
The function index in the minify
array corresponds to the options object with the same index in the minimizerOptions
array.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: [
{}, // Options for the first function (CssMinimizerPlugin.cssnanoMinify)
{}, // Options for the second function (CssMinimizerPlugin.cleanCssMinify)
{}, // Options for the third function
],
minify: [
CssMinimizerPlugin.cssnanoMinify,
CssMinimizerPlugin.cleanCssMinify,
async (data, inputMap, minimizerOptions) => {
// To do something
return {
code: `a{color: red}`,
map: `{"version": "3", ...}`,
warnings: [],
errors: [],
};
},
],
}),
],
},
};
minimizerOptions
Type: Object|Array<Object>
Default: { preset: 'default' }
Cssnano optimisations options.
Object
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
"default",
{
discardComments: { removeAll: true },
},
],
},
}),
],
},
};
Array
The function index in the minify
array corresponds to the options object with the same index in the minimizerOptions
array.
If you use minimizerOptions
like object, all minify
function accept it.
If a parallelization is enabled, the packages in
minimizerOptions
must be required via strings (packageName
orrequire.resolve(packageName)
). In this case, we shouldn't userequire
/import
.
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: require.resolve("cssnano-preset-simple"),
},
}),
],
},
};
processorOptions
(⚠ only cssnano)Type: Object
Default: { from: assetName }
Allows filtering options processoptions
for the cssnano.
The parser
, stringifier
and syntax
can be either a function or a string indicating the module that will be imported.
[!WARNING]
If a function is passed, the
parallel
option must be disabled..
import sugarss from "sugarss";
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
parallel: false,
minimizerOptions: {
processorOptions: {
parser: sugarss,
},
},
}),
],
},
};
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
processorOptions: {
parser: "sugarss",
},
},
}),
],
},
};
warningsFilter
Type: Function<(warning, file, source) -> Boolean>
Default: () => true
Allow filtering css-minimizer warnings (By default cssnano).
Return true
to keep the warning, a falsy value (false
/null
/undefined
) otherwise.
[!WARNING]
The
source
argument will containundefined
if you don't use source maps.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
warningsFilter: (warning, file, source) => {
if (/Dropping unreachable code/i.test(warning)) {
return true;
}
if (/file\.css/i.test(file)) {
return true;
}
if (/source\.css/i.test(source)) {
return true;
}
return false;
},
}),
],
},
};
Don't forget to enable sourceMap
options for all loaders.
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
devtool: "source-map",
module: {
rules: [
{
test: /.s?css$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: "css-loader", options: { sourceMap: true } },
{ loader: "sass-loader", options: { sourceMap: true } },
],
},
],
},
optimization: {
minimizer: [new CssMinimizerPlugin()],
},
plugins: [new MiniCssExtractPlugin()],
};
Remove all comments (including comments starting with /*!
).
module.exports = {
optimization: {
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
"default",
{
discardComments: { removeAll: true },
},
],
},
}),
],
},
};
webpack.config.js
module.exports = {
// Uncomment if you need source maps
// devtool: "source-map",
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.cssoMinify,
// Uncomment this line for options
// minimizerOptions: { restructure: false },
}),
],
},
};
webpack.config.js
module.exports = {
// Uncomment if you need source maps
// devtool: "source-map",
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.cleanCssMinify,
// Uncomment this line for options
// minimizerOptions: { compatibility: 'ie11,-properties.merging' },
}),
],
},
};
webpack.config.js
module.exports = {
// Uncomment if you need source maps
// devtool: "source-map",
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.esbuildMinify,
}),
],
},
};
@parcel/css
webpack.config.js
module.exports = {
// Uncomment if you need source maps
// devtool: "source-map",
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.lightningCssMinify,
// Uncomment this line for options
// minimizerOptions: { targets: { ie: 11 }, drafts: { nesting: true } },
}),
],
},
};
webpack.config.js
module.exports = {
// Uncomment if you need source maps
// devtool: "source-map",
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.swcMinify,
// Uncomment this line for options
// minimizerOptions: {},
}),
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
The DefinePlugin
replaces variables in your code with other values or expressions at compile time. This can be useful for allowing different behavior between development builds and production builds. If you perform logging in your development build but not in the production build you might use a global constant to determine whether logging takes place. That's where DefinePlugin
shines, set it and forget it rules for development and production builds.
new webpack.DefinePlugin({
// Definitions...
});
Each key passed into DefinePlugin
is an identifier or multiple identifiers joined with .
.
typeof
to the key, it's only defined for typeof calls.The values will be inlined into the code allowing a minification pass to remove the redundant conditional.
new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify('5fa3b9'),
BROWSER_SUPPORTS_HTML5: true,
TWO: '1+1',
'typeof window': JSON.stringify('object'),
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
});
console.log('Running App version ' + VERSION);
if (!BROWSER_SUPPORTS_HTML5) require('html5shiv');
if (!PRODUCTION) {
console.log('Debug info');
}
if (PRODUCTION) {
console.log('Production log');
}
After passing through webpack with no minification results in:
if (!true) {
console.log('Debug info');
}
if (true) {
console.log('Production log');
}
and then after a minification pass results in:
console.log('Production log');
Enable/disable features in production/development build using feature flags.
new webpack.DefinePlugin({
NICE_FEATURE: JSON.stringify(true),
EXPERIMENTAL_FEATURE: JSON.stringify(false),
});
Use a different service URL in production/development builds:
new webpack.DefinePlugin({
SERVICE_URL: JSON.stringify('https://dev.example.com'),
});
runtimeValue
function (getterFunction, [string] | true | object) => getterFunction()
It is possible to define variables with values that rely on files and will be re-evaluated when such files change in the file system. This means webpack will rebuild when such watched files change.
There're two arguments for webpack.DefinePlugin.runtimeValue
function:
The first argument is a function(module, key, version)
that should return the value to be assigned to the definition.
The second argument could either be an array of file paths to watch for or a true
to flag the module as uncacheable. Since 5.26.0, it can also take an object argument with the following properties:
fileDependencies?: string[]
A list of files the function depends on.contextDependencies?: string[]
A list of directories the function depends on.missingDependencies?: string[]
A list of not existing files the function depends on.buildDependencies?: string[]
A list of build dependencies the function depends on.version?: string | () => string
A version of the function.const fileDep = path.resolve(__dirname, 'sample.txt');
new webpack.DefinePlugin({
BUILT_AT: webpack.DefinePlugin.runtimeValue(Date.now, {
fileDependencies: [fileDep],
}),
});
The value of BUILT_AT
would be the time at which the 'sample.txt'
was last updated in the file system, e.g. 1597953013291
.
The DllPlugin
and DllReferencePlugin
provide means to split bundles in a way that can drastically improve build time performance. The term "DLL" stands for Dynamic-link library which was originally introduced by Microsoft.
This plugin is used in a separate webpack configuration exclusively to create a dll-only-bundle. It creates a manifest.json
file, which is used by the DllReferencePlugin
to map dependencies.
context
(optional): context of requests in the manifest file (defaults to the webpack context.)format
(boolean = false): If true
, manifest json file (output) will be formatted.name
: name of the exposed dll function (TemplatePaths: [fullhash]
, [chunkhash]
, [contenthash]
, & [name]
)path
: absolute path to the manifest json file (output)entryOnly
(boolean = true): if true
, only entry points will be exposedtype
: type of the dll bundlenew webpack.DllPlugin(options);
Creates a manifest.json
which is written to the given path
. It contains mappings from require and import requests to module ids. It is used by the DllReferencePlugin
.
Combine this plugin with output.library
option to expose (aka, put into the global scope) the dll function.
This plugin is used in the primary webpack config, it references the dll-only-bundle(s) to require pre-built dependencies.
context
: (absolute path) context of requests in the manifest (or content property)extensions
: Extensions used to resolve modules in the dll bundle (only used when using 'scope').manifest
: an object containing content
and name
or a string to the absolute path of the JSON manifest to be loaded upon compilationcontent
(optional): the mappings from request to module id (defaults to manifest.content
)name
(optional): an identifier where the dll is exposed (defaults to manifest.name
) (see also externals
)scope
(optional): prefix which is used for accessing the content of the dllsourceType
(optional): how the dll is exposed (libraryTarget)new webpack.DllReferencePlugin(options);
References a dll manifest file to map dependency names to module ids, then requires them as needed using the internal __webpack_require__
function.
This plugin can be used in two different modes, scoped and mapped.
The content of the dll is accessible under a module prefix. i.e. with scope = 'xyz'
a file abc
in the dll can be access via require('xyz/abc')
.
The content of the dll is mapped to the current directory. If a required file matches a file in the dll (after resolving), then the file from the dll is used instead.
Because this happens after resolving every file in the dll bundle, the same paths must be available for the consumer of the dll bundle. i.e. if the dll contains lodash
and the file abc
, require('lodash')
and require('./abc')
will be used from the dll, rather than building them into the main bundle.
webpack.vendor.config.js
const path = require('path');
new webpack.DllPlugin({
context: __dirname,
name: '[name]_[fullhash]',
path: path.join(__dirname, 'manifest.json'),
});
webpack.app.config.js
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./manifest.json'),
scope: 'xyz',
sourceType: 'commonjs2',
});
Two separate example folders. Demonstrates scope and context.
The EnvironmentPlugin
is shorthand for using the DefinePlugin
on process.env
keys.
The EnvironmentPlugin
accepts either an array of keys or an object mapping its keys to their default values.
new webpack.EnvironmentPlugin(['NODE_ENV', 'DEBUG']);
This is equivalent to the following DefinePlugin
application:
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.DEBUG': JSON.stringify(process.env.DEBUG),
});
Alternatively, the EnvironmentPlugin
supports an object, which maps keys to their default values. The default value for a key is taken if the key is undefined in process.env
.
new webpack.EnvironmentPlugin({
NODE_ENV: 'development', // use 'development' unless process.env.NODE_ENV is defined
DEBUG: false,
});
Example:
Let's investigate the result when running the previous EnvironmentPlugin
configuration on a test file entry.js
:
if (process.env.NODE_ENV === 'production') {
console.log('Welcome to production');
}
if (process.env.DEBUG) {
console.log('Debugging output');
}
When executing NODE_ENV=production webpack
in the terminal to build, entry.js
becomes this:
if ('production' === 'production') {
// <-- 'production' from NODE_ENV is taken
console.log('Welcome to production');
}
if (false) {
// <-- default value is taken
console.log('Debugging output');
}
Running DEBUG=false webpack
yields:
if ('development' === 'production') {
// <-- default value is taken
console.log('Welcome to production');
}
if ('false') {
// <-- 'false' from DEBUG is taken
console.log('Debugging output');
}
The following EnvironmentPlugin
configuration provides process.env.GIT_VERSION
(such as "v5.4.0-2-g25139f57f") and process.env.GIT_AUTHOR_DATE
(such as "2020-11-04T12:25:16+01:00") corresponding to the last Git commit of the repository:
const child_process = require('child_process');
function git(command) {
return child_process.execSync(`git ${command}`, { encoding: 'utf8' }).trim();
}
new webpack.EnvironmentPlugin({
GIT_VERSION: git('describe --always'),
GIT_AUTHOR_DATE: git('log -1 --format=%aI'),
});
The third-party DotenvPlugin
(dotenv-webpack
) allows you to expose (a subset of) dotenv variables:
// .env
DB_HOST=127.0.0.1
DB_PASS=foobar
S3_API=mysecretkey
new Dotenv({
path: './.env', // Path to .env file (this is the default)
safe: true, // load .env.example (defaults to "false" which does not use dotenv-safe)
});
This version of eslint-webpack-plugin only works with webpack 5. For the webpack 4, see the 2.x branch.
This plugin uses eslint
to find and fix problems in your JavaScript code
To begin, you'll need to install eslint-webpack-plugin
:
npm install eslint-webpack-plugin --save-dev
or
yarn add -D eslint-webpack-plugin
or
pnpm add -D eslint-webpack-plugin
[!NOTE]
You also need to install
eslint >= 8
from npm, if you haven't already:
npm install eslint --save-dev
or
yarn add -D eslint
or
pnpm add -D eslint
Then add the plugin to your webpack config. For example:
const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
// ...
plugins: [new ESLintPlugin(options)],
// ...
};
You can pass eslint options.
[!NOTE]
The config option you provide will be passed to the
ESLint
class. This is a different set of options than what you'd specify inpackage.json
or.eslintrc
. See the eslint docs for more details.
[!WARNING]
In eslint-webpack-plugin version 1 the options were passed to the now deprecated CLIEngine.
cache
type cache = boolean;
true
The cache is enabled by default to decrease execution time.
cacheLocation
type cacheLocation = string;
node_modules/.cache/eslint-webpack-plugin/.eslintcache
Specify the path to the cache location. Can be a file or a directory.
configType
type configType = 'flat' | 'eslintrc';
eslintrc
Specify the type of configuration to use with ESLint.
eslintrc
is the classic configuration format available in most ESLint versions.flat
is the new format introduced in ESLint 8.21.0.The new configuration format is explained in its own documentation.
This configuration format being considered as experimental, it is not exported in the main ESLint module in ESLint 8. You need to set your
eslintPath
toeslint/use-at-your-own-risk
for this config format to work.
context
type context = string;
compiler.context
A string indicating the root of your files.
eslintPath
type eslintPath = string;
eslint
Path to eslint
instance that will be used for linting. If the eslintPath
is a folder like a official eslint, or specify a formatter
option. now you don't have to install eslint
.
extensions
type extensions = string | Array<string>;
'js'
Specify extensions that should be checked.
exclude
type exclude = string | Array<string>;
'node_modules'
Specify the files and/or directories to exclude. Must be relative to options.context
.
resourceQueryExclude
type resourceQueryExclude = RegExp | Array<RegExp>;
[]
Specify the resource query to exclude.
files
type files = string | Array<string>;
null
Specify directories, files, or globs. Must be relative to options.context
.
Directories are traversed recursively looking for files matching options.extensions
.
File and glob patterns ignore options.extensions
.
fix
type fix = boolean;
false
Will enable ESLint autofix feature.
Be careful: this option will change source files.
formatter
type formatter = string| (
results: Array<import('eslint').ESLint.LintResult>,
data?: import('eslint').ESLint.LintResultData | undefined
) => string
'stylish'
Accepts a function that will have one argument: an array of eslint messages (object). The function must return the output as a string. You can use official eslint formatters.
lintDirtyModulesOnly
type lintDirtyModulesOnly = boolean;
false
Lint only changed files, skip lint on start.
threads
type threads = boolean | number;
false
Will run lint tasks across a thread pool. The pool size is automatic unless you specify a number.
By default the plugin will auto adjust error reporting depending on eslint errors/warnings counts.
You can still force this behavior by using emitError
or emitWarning
options:
emitError
type emitError = boolean;
true
The errors found will always be emitted, to disable set to false
.
emitWarning
type emitWarning = boolean;
true
The warnings found will always be emitted, to disable set to false
.
failOnError
type failOnError = boolean;
true
Will cause the module build to fail if there are any errors, to disable set to false
.
failOnWarning
type failOnWarning = boolean;
false
Will cause the module build to fail if there are any warnings, if set to true
.
quiet
type quiet = boolean;
false
Will process and report errors only and ignore warnings, if set to true
.
outputReport
type outputReport =
| boolean
| {
filePath?: string | undefined;
formatter?:
| (
| string
| ((
results: Array<import('eslint').ESLint.LintResult>,
data?: import('eslint').ESLint.LintResultData | undefined,
) => string)
)
| undefined;
};
false
Write the output of the errors to a file, for example a checkstyle xml file for use for reporting on Jenkins CI.
The filePath
is an absolute path or relative to the webpack config: output.path
.
You can pass in a different formatter
for the output file,
if none is passed in the default/configured formatter will be used.
This plugin enables more fine grained control of source map generation. It is also enabled automatically by certain settings of the devtool
configuration option.
new webpack.EvalSourceMapDevToolPlugin(options);
The following options are supported:
test
(string|RegExp|array
): Include source maps for modules based on their extension (defaults to .js
and .css
).
include
(string|RegExp|array
): Include source maps for module paths that match the given value.
exclude
(string|RegExp|array
): Exclude modules that match the given value from source map generation.
append
(string|function
): Appends the given value to the original asset. Usually the #sourceMappingURL
comment. [url]
is replaced with a URL to the source map file.
Starting from version 5.84.0, webpack allows the append
option to be a function that accepts path data and an asset info object as arguments, and returns a string.
(pathData: PathData, assetInfo?: AssetInfo) => string;
moduleFilenameTemplate
(string
): See output.devtoolModuleFilenameTemplate
.
module
(boolean
): Indicates whether loaders should generate source maps (defaults to true
).
columns
(boolean
): Indicates whether column mappings should be used (defaults to true
).
protocol
(string
): Allows user to override default protocol (webpack-internal://
)
The following examples demonstrate some common use cases for this plugin.
You can use the following code to replace the configuration option devtool: eval-source-map
with an equivalent custom plugin configuration:
module.exports = {
// ...
devtool: false,
plugins: [new webpack.EvalSourceMapDevToolPlugin({})],
};
The following code would exclude source maps for any modules in the vendor.js
bundle:
new webpack.EvalSourceMapDevToolPlugin({
exclude: ['vendor.js'],
});
This plugin will cause hashes to be based on the relative path of the module, generating a four character string as the module id. Suggested for use in production.
new webpack.ids.HashedModuleIdsPlugin({
// Options...
});
This plugin supports the following options:
context
: The context directory (absolute path) for creating names.hashFunction
: The hashing algorithm to use, defaults to 'md4'
. All functions from Node.JS' crypto.createHash
are supported.hashDigest
: The encoding to use when generating the hash, defaults to 'base64'
. All encodings from Node.JS' hash.digest
are supported.hashDigestLength
: The prefix length of the hash digest to use, defaults to 4
. Note that some generated ids might be longer than specified here, to avoid module id collisions.Here's an example of how this plugin might be used:
new webpack.ids.HashedModuleIdsPlugin({
context: __dirname,
hashFunction: 'sha256',
hashDigest: 'hex',
hashDigestLength: 20,
});
Enables Hot Module Replacement, otherwise known as HMR.
Enabling HMR is straightforward and in most cases no options are necessary.
new webpack.HotModuleReplacementPlugin({
// Options...
});
This plugin can use 3 tools to optimize and minify your HTML:
swc
- very fast Rust-based platform for the Web.html-minifier-terser
(by default) - JavaScript-based HTML minifier.@minify-html/node
- A Rust HTML minifier meticulously optimised for speed and effectiveness, with bindings for other languages.To begin, you'll need to install html-minimizer-webpack-plugin
:
npm install html-minimizer-webpack-plugin --save-dev
or
yarn add -D html-minimizer-webpack-plugin
or
pnpm add -D html-minimizer-webpack-plugin
Additional step: If you want to use @swc/html
you need to install it:
npm install @swc/html --save-dev
or
yarn add -D @swc/html
or
pnpm add -D @swc/html
Additional step: If you want to use @minify-html/node
you need to install it:
npm install @minify-html/node --save-dev
or
yarn add -D @minify-html/node
or
pnpm add -D @minify-html/node
Then add the plugin to your webpack
configuration. For example:
webpack.config.js
const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
type: "asset/resource",
},
],
},
plugins: [
new CopyPlugin({
patterns: [
{
context: path.resolve(__dirname, "dist"),
from: "./src/*.html",
},
],
}),
],
optimization: {
minimize: true,
minimizer: [
// For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
// `...`
// For `html-minifier-terser`:
//
new HtmlMinimizerPlugin(),
// For `@swc/html`:
//
// HTML documents - HTML documents with `Doctype` and `<html>/`<head>`/`<body>` tags
//
// Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L5
//
// new HtmlMinimizerPlugin({
// minify: HtmlMinimizerPlugin.swcMinify,
// minimizerOptions: {}
// })
//
//
// HTML fragments - HTML fragments, i.e. HTML files without doctype or used in `<template>` tags or HTML parts which injects into another HTML parts
//
// Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L38
//
// new HtmlMinimizerPlugin({
// minify: HtmlMinimizerPlugin.swcMinifyFragment,
// minimizerOptions: {}
// })
],
},
};
This will enable HTML optimization only in production mode.
If you want to run it also in development set the optimization.minimize
option to true
.
And run webpack
via your preferred method.
[!NOTE]
Removing and collapsing spaces in the tools differ (by default).
@swc/html
- remove and collapse whitespaces only in safe places (for example - aroundhtml
andbody
elements, inside thehead
element and between metadata elements -<meta>
/script
/link
/etc.)html-minifier-terser
- always collapse multiple whitespaces to 1 space (never remove it entirely), but you can change it usingoptions
@minify-html/node
- please read documentation https://github.com/wilsonzlin/minify-html#whitespace
test
Type:
type test = string | RegExp | Array<string | RegExp>;
Default: /\.html(\?.*)?$/i
Test to match files against.
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
test: /\.foo\.html/i,
}),
],
},
};
include
Type:
type include = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to include.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
include: /\/includes/,
}),
],
},
};
exclude
Type:
type exclude = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to exclude.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
exclude: /\/excludes/,
}),
],
},
};
parallel
Type:
type parallel = undefined | boolean | number;
Default: true
Use multi-process parallel running to improve the build speed.
Default number of concurrent runs: os.cpus().length - 1
.
[!NOTE]
Parallelization can speed up your build significantly and is therefore highly recommended.
boolean
Enable/disable multi-process parallel running.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
parallel: true,
}),
],
},
};
number
Enable multi-process parallel running and set number of concurrent runs.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
parallel: 4,
}),
],
},
};
minify
Type:
type minify =
| ((
data: { [file: string]: string },
minimizerOptions: {
[key: string]: any;
},
) => {
code: string;
errors?: unknown[] | undefined;
warnings?: unknown[] | undefined;
})
| ((
data: { [file: string]: string },
minimizerOptions: {
[key: string]: any;
},
) => {
code: string;
errors?: unknown[] | undefined;
warnings?: unknown[] | undefined;
})[];
Default: HtmlMinimizerPlugin.htmlMinifierTerser
Allows you to override default minify function. By default, plugin uses html-minifier-terser package.
We currently support:
HtmlMinimizerPlugin.swcMinify
(used to compress HTML documents, i.e. with HTML doctype and <html>
/<body>
/<head>
tags)HtmlMinimizerPlugin.swcMinifyFragment
(used to compress HTML fragments, i.e. when you have part of HTML which will be inserted into another HTML parts)HtmlMinimizerPlugin.htmlMinifierTerser
HtmlMinimizerPlugin.minifyHtmlNode
[!NOTE]
The difference between
swcMinify
andswcMinifyFragment
is the error reporting. You will get errors (invalid or broken syntax) if you have them in your HTML document or fragment. Which allows you to see all the errors and problems at the build stage.
Useful for using and testing unpublished versions or forks.
[!WARNING]
Always use
require
insideminify
function whenparallel
option enabled.
function
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minimizerOptions: {
collapseWhitespace: true,
},
minify: (data, minimizerOptions) => {
const htmlMinifier = require("html-minifier-terser");
const [[filename, input]] = Object.entries(data);
return {
code: htmlMinifier.minify(input, minimizerOptions),
warnings: [],
errors: [],
};
},
}),
],
},
};
array
If an array of functions is passed to the minify
option, the minimizerOptions
can be an array or an object.
If minimizerOptions
is array, the function index in the minify
array corresponds to the options object with the same index in the minimizerOptions
array.
If you use minimizerOptions
like object, all minify
function accept it.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minimizerOptions: [
// Options for the first function (HtmlMinimizerPlugin.htmlMinifierTerser)
{
collapseWhitespace: true,
},
// Options for the second function
{},
],
minify: [
HtmlMinimizerPlugin.htmlMinifierTerser,
(data, minimizerOptions) => {
const [[filename, input]] = Object.entries(data);
// To do something
return {
code: `optimised code`,
warnings: [],
errors: [],
};
},
],
}),
],
},
};
minimizerOptions
Type:
type minimizerOptions =
| {
[key: string]: any;
}
| Array<{
[key: string]: any;
}>;
Default: { caseSensitive: true, collapseWhitespace: true, conservativeCollapse: true, keepClosingSlash: true, minifyCSS: true, minifyJS: true, removeComments: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, }
Html-minifier-terser
optimizations options.
object
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minimizerOptions: {
collapseWhitespace: false,
},
}),
],
},
};
array
The function index in the minify
array corresponds to the options object with the same index in the minimizerOptions
array.
If you use minimizerOptions
like object, all minify
function accept it.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minimizerOptions: [
// Options for the first function (HtmlMinimizerPlugin.htmlMinifierTerser)
{
collapseWhitespace: true,
},
// Options for the second function
{},
],
minify: [
HtmlMinimizerPlugin.htmlMinifierTerser,
(data, minimizerOptions) => {
const [[filename, input]] = Object.entries(data);
// To do something
return {
code: `optimised code`,
warnings: [],
errors: [],
};
},
],
}),
],
},
};
swc/html
Available options
.
HTML Documents:
const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
type: "asset/resource",
},
],
},
plugins: [
new CopyPlugin({
patterns: [
{
context: path.resolve(__dirname, "dist"),
from: "./src/*.html",
},
],
}),
],
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minify: HtmlMinimizerPlugin.swcMinify,
minimizerOptions: {
// Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L5
},
}),
],
},
};
HTML Fragments:
const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
type: "asset/resource",
},
],
},
plugins: [
new CopyPlugin({
patterns: [
{
context: path.resolve(__dirname, "dist"),
from: "./src/*.html",
},
],
}),
],
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
test: /\.template\.html$/i,
minify: HtmlMinimizerPlugin.swcMinifyFragment,
minimizerOptions: {
// Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L38
},
}),
],
},
};
@minify-html/node
Available options
.
HTML Documents:
const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
type: "asset/resource",
},
],
},
plugins: [
new CopyPlugin({
patterns: [
{
context: path.resolve(__dirname, "dist"),
from: "./src/*.html",
},
],
}),
],
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minify: HtmlMinimizerPlugin.minifyHtmlNode,
minimizerOptions: {
// Options - https://github.com/wilsonzlin/minify-html#minification
},
}),
],
},
};
You can use multiple HtmlMinimizerPlugin
plugins to compress different files with the different minify
function.
Please take a moment to read our contributing guidelines if you haven't yet done so.
The HtmlWebpackPlugin
simplifies creation of HTML files to serve your webpack bundles. This is especially useful for webpack bundles that include a hash in the filename which changes every compilation. You can either let the plugin generate an HTML file for you, supply your own template using lodash templates, or use your own loader.
npm install --save-dev html-webpack-plugin
The plugin will generate an HTML5 file for you that includes all your webpack
bundles in the body using script
tags. Add the plugin to your webpack
configuration as follows:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
entry: 'index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index_bundle.js',
},
plugins: [new HtmlWebpackPlugin()],
};
This will generate a file dist/index.html
containing the following:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>webpack App</title>
</head>
<body>
<script src="index_bundle.js"></script>
</body>
</html>
If you have multiple webpack entry points, they will all be included with <script>
tags in the generated HTML.
If you have any CSS assets in webpack's output (for example, CSS extracted with the MiniCssExtractPlugin) then these will be included with <link>
tags in the <head>
element of generated HTML.
For all configuration options, please see the plugin documentation.
The plugin supports addons. For a list see the documentation.
IgnorePlugin prevents the generation of modules for import
or require
calls matching the regular expressions or filter functions.
resourceRegExp
: A RegExp to test the resource against.contextRegExp
: (optional) A RegExp to test the context (directory) against.new webpack.IgnorePlugin({ resourceRegExp, contextRegExp });
checkResource (resource, context)
A Filter function that receives resource
and context
as arguments, must return boolean.new webpack.IgnorePlugin({
checkResource(resource) {
// do something with resource
return true | false;
},
});
As of moment 2.18, all locales are bundled together with the core library (see this GitHub issue).
The resourceRegExp
parameter passed to IgnorePlugin
is not tested against the resolved file names or absolute module names being imported or required, but rather against the string passed to require
or import
within the source code where the import is taking place. For example, if you're trying to exclude node_modules/moment/locale/*.js
, this won't work:
-new webpack.IgnorePlugin({ resourceRegExp: /moment\/locale\// });
Rather, because moment
imports with this code:
require('./locale/' + name);
...your first regexp must match that './locale/'
string. The second contextRegExp
parameter is then used to select specific directories from where the import took place. The following will cause those locale files to be ignored:
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/,
});
...which means "any require statement matching './locale'
from any directories ending with 'moment'
will be ignored.
Plugin and Loader for webpack to optimize (compress) all images using imagemin. Do not worry about size of images, now they are always optimized/compressed.
This plugin can use 4 tools to optimize/generate images:
imagemin
- optimize your images by default, since it is stable and works with all types of imagessquoosh
- while working in experimental mode with .jpg
, .jpeg
, .png
, .webp
, .avif
file types.sharp
- High performance Node.js image processing, the fastest module to resize and compress JPEG, PNG, WebP, AVIF and TIFF images. Uses the libvips library.svgo
- tool for optimizing SVG vector graphics files. Supports only SVG files minification.[!WARNING]
By default we don't install anything
To begin, you'll need to install image-minimizer-webpack-plugin
and image minimizer/generator:
npm install image-minimizer-webpack-plugin imagemin --save-dev
[!WARNING]
imagemin uses plugin to optimize/generate images, so you need to install them too
squoosh
:npm install image-minimizer-webpack-plugin @squoosh/lib --save-dev
npm install image-minimizer-webpack-plugin sharp --save-dev
svgo
:npm install image-minimizer-webpack-plugin svgo --save-dev
Images can be optimized in two modes:
imagemin
[!NOTE]
- imagemin-mozjpeg can be configured in lossless and lossy mode.
- 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
npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo --save-dev
Recommended imagemin plugins for lossy optimization
npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo --save-dev
For imagemin-svgo
v9.0.0+ need use svgo configuration
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
// 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 configuration here https://github.com/svg/svgo#configuration
[
"svgo",
{
plugins: [
{
name: "preset-default",
params: {
overrides: {
removeViewBox: false,
addAttributesToSVGElement: {
params: {
attributes: [
{ xmlns: "http://www.w3.org/2000/svg" },
],
},
},
},
},
},
],
},
],
],
},
},
}),
],
},
};
squoosh
npm install @squoosh/lib --save-dev
Recommended @squoosh/lib
options for lossy optimization
For lossy optimization we recommend using the default settings of @squoosh/lib
package.
The default values and supported file types for each option can be found in the codecs.ts file under codecs.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.squooshMinify,
options: {
// Your options for `squoosh`
},
},
}),
],
},
};
Recommended squoosh
options for lossless optimization
For lossless optimization we recommend using the options listed below in minimizer.options.encodeOptions
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.squooshMinify,
options: {
encodeOptions: {
mozjpeg: {
// That setting might be close to lossless, but it’s not guaranteed
// https://github.com/GoogleChromeLabs/squoosh/issues/85
quality: 100,
},
webp: {
lossless: 1,
},
avif: {
// https://github.com/GoogleChromeLabs/squoosh/blob/dev/codecs/avif/enc/README.md
cqLevel: 0,
},
},
},
},
}),
],
},
};
sharp
npm install sharp --save-dev
Recommended sharp
options for lossy optimization
For lossy optimization we recommend using the default settings of sharp
package.
The default values and supported file types for each option can be found in the sharp documentation.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.sharpMinify,
options: {
encodeOptions: {
// Your options for `sharp`
// https://sharp.pixelplumbing.com/api-output
},
},
},
}),
],
},
};
Recommended sharp
options for lossless optimization
For lossless optimization we recommend using the options listed below in minimizer.options.encodeOptions
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.sharpMinify,
options: {
encodeOptions: {
jpeg: {
// https://sharp.pixelplumbing.com/api-output#jpeg
quality: 100,
},
webp: {
// https://sharp.pixelplumbing.com/api-output#webp
lossless: true,
},
avif: {
// https://sharp.pixelplumbing.com/api-output#avif
lossless: true,
},
// png by default sets the quality to 100%, which is same as lossless
// https://sharp.pixelplumbing.com/api-output#png
png: {},
// gif does not support lossless compression at all
// https://sharp.pixelplumbing.com/api-output#gif
gif: {},
},
},
},
}),
],
},
};
svgo
npm install svgo --save-dev
Recommended svgo
options for optimization
For optimization we recommend using the options listed below in minimizer.options.encodeOptions
.
The default values for plugins can be found in the svgo plugins source code.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(svg)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.svgoMinify,
options: {
encodeOptions: {
// Pass over SVGs multiple times to ensure all optimizations are applied. False by default
multipass: true,
plugins: [
// set of built-in plugins enabled by default
// see: https://github.com/svg/svgo#default-preset
"preset-default",
],
},
},
},
}),
],
},
};
If you want to use loader
or plugin
standalone see sections below, but this is not recommended.
By default, plugin configures loader
(please use the loader
option if you want to disable this behaviour), therefore you should not setup standalone loader when you use a plugin setup.
Loader optimizes or generates images using options, so inlined images via data
URI (i.e. data:
) will be optimized or generated too, not inlined images will be optimized too.
squoosh
and sharp
currently)The plugin supports the following query parameters:
width
/w
- allows you to set the image width
height
/h
- allows you to set the image height
as
- to specify the preset option
Only supported for sharp
currently:
unit
/u
- can be px
or percent
and allows you to resize by a percentage of the image's size.
Examples:
const myImage1 = new URL("image.png?width=150&height=120", import.meta.url);
const myImage2 = new URL("image.png?w=150&h=120", import.meta.url);
// You can omit one of the parameters to auto-scale
const myImage3 = new URL("image.png?w=150", import.meta.url);
// It works with the `preset` query parameter
const myImage4 = new URL("image.png?as=webp&w=150&h=120", import.meta.url);
// You can use `auto` to reset `width` or `height` from the `preset` option
const myImage5 = new URL("image.png?as=webp&w=150&h=auto", import.meta.url);
// You can use `unit` to get the non-retina resize of images that are retina sized
const myImage6 = new URL("image.png?width=50&unit=percent", import.meta.url);
.class {
background: url("./image.png?width=150&height=120");
}
<picture>
<source srcset="photo.jpg?as=avif&width=150&height=120" type="image/avif" />
<source srcset="photo.jpg?as=webp&width=150&height=120" type="image/webp" />
<img src="photo.jpg?width=150&height=120" alt="photo" />
</picture>
[!NOTE]
You need to setup
avif
andwebp
presets, example for webp.
In your webpack.config.js
, add the ImageMinimizerPlugin.loader
and specify the asset modules options (if you use images in import
):
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
// We recommend using only for the "production" mode
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: ImageMinimizerPlugin.loader,
enforce: "pre",
options: {
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
},
},
],
},
],
},
};
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
// Extend default minimizer, i.e. `terser-webpack-plugin` for JS
"...",
// We recommend using only for the "production" mode
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
// Disable `loader`
loader: false,
}),
],
},
};
test
Type:
type test = string | RegExp | Array<string | RegExp>;
Default: /\.(jpe?g\|png\|gif\|tif\|webp\|svg\|avif)\$/i
Test to match files against.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
}),
],
},
};
include
Type:
type include = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to include.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
include: /\/includes/,
}),
],
},
};
exclude
Type:
type exclude = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to exclude.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
exclude: /\/excludes/,
}),
],
},
};
minimizer
Type:
type minimizer =
| {
implementation: (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
options?:
| {
[key: string]: any;
}
| undefined;
filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
filename?:
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
}
| Array<{
implementation: (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
options?:
| {
[key: string]: any;
}
| undefined;
filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
filename?:
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
}>;
Default: undefined
Allows to setup default minify function.
ImageMinimizerPlugin.imageminMinify
ImageMinimizerPlugin.squooshMinify
ImageMinimizerPlugin.sharpMinify
ImageMinimizerPlugin.svgoMinify
imagemin
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
// Implementation
implementation: ImageMinimizerPlugin.imageminMinify,
// Options
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
More information and examples here.
squoosh
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
// Implementation
implementation: ImageMinimizerPlugin.squooshMinify,
// Options
options: {
encodeOptions: {
mozjpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
More information and examples here.
sharp
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
// Implementation
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
More information and examples here.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: async (original, options) => {
const inputExt = path.extname(original.filename).toLowerCase();
if (inputExt !== ".xxx") {
// Return `null` if the implementation does not support this file type
return null;
}
let result;
try {
result = await minifyAndReturnBuffer(original.data);
} catch (error) {
// Store error and return `null` if there was an error
original.errors.push(error);
return null;
}
return {
filename: original.filename,
data: result,
warnings: [...original.warnings],
errors: [...original.errors],
info: {
...original.info,
// Please always set it to prevent double minification
minimized: true,
// Optional
minimizedBy: ["custom-name-of-minimication"],
},
};
},
options: {
// Custom options
},
},
}),
],
},
};
Allows to setup multiple minimizers.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: [
{
// `sharp` will handle all bitmap formats (JPG, PNG, GIF, ...)
implementation: ImageMinimizerPlugin.sharpMinify,
// exclude SVG if implementation support it. Not required for `sharp`.
// filter: (source, sourcePath) => !(/\.(svg)$/i.test(sourcePath)),
options: {
encodeOptions: {
// Your options for `sharp`
// https://sharp.pixelplumbing.com/api-output
},
},
},
{
// `svgo` will handle vector images (SVG)
implementation: ImageMinimizerPlugin.svgoMinify,
options: {
encodeOptions: {
// Pass over SVGs multiple times to ensure all optimizations are applied. False by default
multipass: true,
plugins: [
// set of built-in plugins enabled by default
// see: https://github.com/svg/svgo#default-preset
"preset-default",
],
},
},
},
],
}),
],
},
};
implementation
Type:
type implementation = (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?: BasicTransformerOptions<T>,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
Default: undefined
Configure the default implementation
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
// Implementation
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
options
Type:
type options = {
[key: string]: any;
};
Default: undefined
Options for the implementation
option (i.e. options for imagemin
/squoosh
/sharp
/custom implementation).
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
filter
Type:
type filter = (source: Buffer, sourcePath: string) => boolean | undefined;
Default: () => true
Allows filtering of images for optimization/generation.
Return true
to optimize the image, false
otherwise.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
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;
},
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
filename
Type:
type filename =
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
Default: undefined
Allows to set the filename.
Supported values see in webpack template strings
, File-level
section.
We also support [width]
and [height]
placeholders (only sharp
and squoosh
).
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
filename: "optimized-[name][ext]",
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
Example function
usage:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
filename: () => "optimized-[name][ext]",
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
generator
Type:
type generator = Array<{
implementation: (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
options?:
| {
[key: string]: any;
}
| undefined;
filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
filename?:
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
preset?: string | undefined;
type?: "import" | "asset" | undefined;
}>;
Default: undefined
Allow to setup default generators.
Useful if you need generate webp
/avif
/etc from other formats.
[!WARNING]
If no generator was found for the image (i.e. no
?as=webp
was found in query params), theminimizer
option will be used. Therefore, it is recommended to configure generator outputs optimized image.
[!WARNING]
The option will not work if you disable
loader
(i.e. set theloader
option tofalse
).
ImageMinimizerPlugin.imageminGenerate
ImageMinimizerPlugin.squooshGenerate
ImageMinimizerPlugin.sharpGenerate
imagemin
Example webp
generator:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
// Please specify only one plugin here, multiple plugins will not work
plugins: ["imagemin-webp"],
},
},
],
}),
],
},
};
squoosh
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.squooshGenerate,
options: {
encodeOptions: {
// Please specify only one codec here, multiple codecs will not work
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
sharp
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
// Please specify only one codec here, multiple codecs will not work
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
Now you can generate the new image using:
// Old approach for getting URL
import webp from "./file.jpg?as=webp";
// Assets modules
console.log(new URL("./file.jpg?as=webp"));
div {
background: url("./file.jpg?as=webp");
}
You can use ?as=webp
in any type of files.
Example multiple generators:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
webp: {
lossless: false,
},
},
},
},
{
// You can apply generator using `?as=avif`, you can use any name and provide more options
preset: "avif",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
avif: {
lossless: false,
},
},
},
},
],
}),
],
},
};
squoosh
and sharp
generator supports more options, for example you can resize an image:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp-100-50`, you can use any name and provide more options
preset: "webp-100-50",
// implementation: ImageMinimizerPlugin.squooshGenerate,
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
resize: {
enabled: true,
width: 100,
height: 50,
},
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
You can find more information here.
For only sharp
currently, you can even generate the non-retina resizes of images:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp-1x`, you can use any name and provide more options
preset: "webp-1x",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
resize: {
enabled: true,
width: 50,
unit: "percent",
},
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
You can use your own generator implementation.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: async (original, options) => {
const inputExt = path.extname(original.filename).toLowerCase();
if (inputExt !== ".xxx") {
// Store error and return `null` if the implementation does not support this file type
original.errors.push(error);
return null;
}
let result;
try {
result = await minifyAndReturnBuffer(original.data);
} catch (error) {
// Store error and return `null` if there was an error
original.errors.push(error);
return null;
}
return {
filename: original.filename,
data: result,
warnings: [...original.warnings],
errors: [...original.errors],
info: {
...original.info,
// Please always set it to prevent double minification
generated: true,
// Optional
generatedBy: ["custom-name-of-minification"],
},
};
},
options: {
// Your options
},
},
],
}),
],
},
};
type
Type:
type type = "import" | "asset" | undefined;
Default: "import"
Allows you to apply the generator for import
or assets from compilation (useful for copied assets).
By default, generators are applying on import
/require
, but sometimes you need to generate new images from other plugins (for example - copy-webpack-plugin
), if you need this, please set asset
value for the type
option.
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
generator: [
{
// Apply generator for copied assets
type: "asset",
// You can use `ImageMinimizerPlugin.squooshGenerate`
// You can use `ImageMinimizerPlugin.sharpGenerate`
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: ["imagemin-webp"],
},
},
],
}),
],
},
plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
preset
Type:
type preset = string | undefined;
Default: undefined
Configure the name of preset, i.e. you can use it in ?as=name
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
// Implementation
implementation: ImageMinimizerPlugin.sharpMinify,
options: {
encodeOptions: {
jpeg: {
quality: 85,
},
},
},
},
],
}),
],
},
};
implementation
Type:
type implementation = (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
Default: undefined
Configure the default implementation
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
// Implementation
implementation: ImageMinimizerPlugin.sharpMinify,
options: {
encodeOptions: {
jpeg: {
quality: 85,
},
},
},
},
],
}),
],
},
};
options
Type:
type options = {
[key: string]: any;
};
Default: undefined
Options for the implementation
option (i.e. options for imagemin
/squoosh
/sharp
/custom implementation).
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
],
}),
],
},
};
filter
Type:
type filter = (source: Buffer, sourcePath: string) => boolean;
Default: () => true
Allows filtering of images for optimization/generation.
Return true
to optimize the image, false
otherwise.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
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;
},
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
],
}),
],
},
};
filename
Type:
type filename =
| string
| ((
pathData: PathData,
assetInfo?: import("webpack").AssetInfo | undefined,
) => string);
Default: undefined
Allows to set the filename.
Supported values see in webpack template strings
, File-level
section.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
filename: "generated-[name][ext]",
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
],
}),
],
},
};
Example of function
usage:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
filename: () => "generated-[name][ext]",
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
],
}),
],
},
};
severityError
Type:
type severityError = string;
Default: 'error'
Allows to choose how errors are displayed.
Сan have the following values:
'off'
- suppresses errors and warnings'warning'
- emit warnings instead errors'error'
- emit errorswebpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
severityError: "warning",
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
loader
Type:
type loader = boolean;
Default: true
Automatically adding built-in loader
, used to optimize/generate images.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
loader: false,
// `generator` will not work in this case
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
concurrency
Type:
type concurrency = number;
Default: Math.max(1, os.cpus().length - 1)
Maximum number of concurrency optimization processes in one time.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
concurrency: 3,
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
deleteOriginalAssets
Type:
type deleteOriginalAssets = boolean;
Default: true
Allows removing original assets after optimization.
Please use this option if you are set the filename
option for the minimizer
option, disable loader: false
and want to keep optimized and not optimized assets.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
// Disable loader
loader: false,
// Allows to keep original asset and minimized assets with different filenames
deleteOriginalAssets: false,
minimizer: {
filename: "[path][name].webp",
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
minimizer
Type:
type minimizer =
| {
implementation: (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
options?:
| {
[key: string]: any;
}
| undefined;
filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
filename?:
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
}
| Array<{
implementation: (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
options?:
| {
[key: string]: any;
}
| undefined;
filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
filename?:
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
}>;
Default: undefined
Allows to setup default minimizer.
imagemin
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: ImageMinimizerPlugin.loader,
enforce: "pre",
options: {
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
},
},
],
},
};
For more information and supported options please read here.
generator
Type:
type generator = Array<{
implementation: TransformerFunction<T>;
options?: BasicTransformerOptions<T>;
filter?: FilterFn | undefined;
filename?: string | FilenameFn | undefined;
preset?: string | undefined;
type?: "import" | "asset" | undefined;
}>;
Default: undefined
Allow to setup default generators.
Useful if you need generate webp
/avif
/etc from other formats.
imagemin
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: ImageMinimizerPlugin.loader,
enforce: "pre",
options: {
generator: [
{
preset: "webp",
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: ["imagemin-webp"],
},
},
],
},
},
],
},
};
For more information and supported options please read here.
severityError
Type:
type severityError = string;
Default: 'error'
Allows to choose how errors are displayed.
Сan have the following values:
'off'
- suppresses errors and warnings'warning'
- emit warnings instead errors'error'
- emit errorswebpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: ImageMinimizerPlugin.loader,
options: {
severityError: "warning",
minimizerOptions: {
plugins: ["gifsicle"],
},
},
},
],
},
],
},
};
imageminNormalizeConfig(config)
The function normalizes configuration (converts plugins names and options to Function
s) for using in imagemin
package directly.
const imagemin = require("imagemin");
const { imageminNormalizeConfig } = require("image-minimizer-webpack-plugin");
/*
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 imageminConfig = await imageminNormalizeConfig({
plugins: ["jpegtran", ["pngquant", { quality: [0.6, 0.8] }]],
});
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'}, …]
})();
You can use difference options (like progressive
/interlaced
/etc.) based on image size (example - don't do progressive transformation for small images).
What is progressive
image? Answer here
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [["jpegtran", { progressive: true }]],
},
// Only apply this one to files equal to or over 8192 bytes
filter: (source) => {
if (source.byteLength >= 8192) {
return true;
}
return false;
},
},
}),
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [["jpegtran", { progressive: false }]],
},
// Only apply this one to files under 8192
filter: (source) => {
if (source.byteLength < 8192) {
return true;
}
return false;
},
},
}),
],
},
};
webp
imageswebpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: ["imagemin-webp"],
},
},
],
}),
],
},
};
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.squooshMinify,
},
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.squooshGenerate,
options: {
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.sharpMinify,
},
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
webp
images from copied assetswebpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
generator: [
{
type: "asset",
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: ["imagemin-webp"],
},
},
],
}),
],
},
plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.squooshMinify,
},
generator: [
{
type: "asset",
implementation: ImageMinimizerPlugin.squooshGenerate,
options: {
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.sharpMinify,
},
generator: [
{
type: "asset",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
Speed up development by automatically installing & saving dependencies with Webpack.
It is inefficient to Ctrl-C your build script & server just to install a dependency you didn't know you needed until now.
Instead, use require
or import
how you normally would and installation
will happen automatically to install & save missing dependencies while you work!
$ npm install --save-dev install-webpack-plugin
In your webpack.config.js
:
plugins: [
new InstallPlugin()
],
This is equivalent to:
plugins: [
new InstallPlugin({
dependencies: {
peer: true,
},
packageManager: {
type: this.getDefaultPackageManager(),
options: {
dev: false,
quiet: false,
},
},
prompt: true,
});
],
Type: Object
Dependencies related options.
Type: Boolean
Default: true
Install missing peer dependencies.
plugins: [
new InstallPlugin({
dependencies: {
peer: true,
}
}),
],
Type: 'npm' | 'yarn' | 'pnpm' | Object | Function
Package manager to use for installing dependencies.
plugins: [
new InstallPlugin({
packageManager: 'yarn'
},
}),
],
You can provide a Function
to the packageManager
to make it dynamic:
plugins: [
new InstallPlugin({
packageManager: function(module, path) {
return [
"babel-preset-react-hmre",
"webpack-dev-middleware",
"webpack-hot-middleware",
].indexOf(module) !== -1;
},
}),
],
Type: 'npm' | 'yarn' | 'pnpm'
Name of package manager to use for installing dependencies.
Type: Object
Package manager related options.
Type: Array
Provide custom arguments to use with package manager.
plugins: [
new InstallPlugin({
packageManager: {
type: 'npm',
options: {
arguments: ['--ignore-scripts']
}
}
},
}),
],
Type: Boolean
Default: false
Install as development dependencies.
plugins: [
new InstallPlugin({
packageManager: {
type: 'npm',
options: {
dev: true,
}
}
},
}),
],
Type: Boolean
Default: false
Reduce the amount of console logging.
plugins: [
new InstallPlugin({
packageManager: {
type: 'npm',
options: {
quiet: true,
}
}
},
}),
],
Type: Boolean
Default: true
Show a prompt to confirm installation.
plugins: [
new InstallPlugin({
prompt: true,
},
}),
],
^v5.0.0
..babelrc
plugins & presets.require
, import
)@cycle/dom
)lodash.capitalize
)@import "~bootstrap"
)babel-loader
, file-loader
, etc.)require("bundle?lazy!./App"
)peerDependencies
.
(e.g. @cycle/core
will automatically install rx@*
)resolve.alias
& resolve.root
configuration.
(e.g. require("react")
can alias to react-lite
)Please take a moment to read our contributing guidelines if you haven't yet done so.
This is a list of plugins which are used by webpack internally.
Categories of internal plugins:
Plugins affecting the environment of the compiler.
webpack.node.NodeEnvironmentPlugin()
Applies Node.js style filesystem to the compiler.
Plugins affecting the compiler
MemoryCachePlugin()
Adds a cache to the compiler, where modules are cached in memory.
ProgressPlugin(handler)
Hook into the compiler to extract progress information. The handler
must have the signature function(percentage, message)
. Percentage is called with a value between 0 and 1, where 0 indicates the start and 1 the end.
RecordIdsPlugin()
Saves and restores module and chunk ids from records.
Plugins, which add entry chunks to the compilation.
EntryPlugin(context, entry, options)
Adds an entry chunk on compilation. The chunk is named options.name
and contains only one module (plus dependencies). The module is resolved from entry
in context
(absolute path).
PrefetchPlugin(context, request)
Prefetches request
and dependencies to enable a more parallel compilation. It doesn't create any chunk. The module is resolved from request
in context
(absolute path).
JsonpTemplatePlugin(options)
Chunks are wrapped into JSONP-calls. A loading algorithm is included in entry chunks. It loads chunks by adding a <script>
tag.
options
are the output options.
options.jsonpFunction
is the JSONP function.
options.publicPath
is used as path for loading the chunks.
options.chunkFilename
is the filename under that chunks are expected.
node/NodeTemplatePlugin(options)
Chunks are wrapped into Node.js modules exporting the bundled modules. The entry chunks loads chunks by requiring them.
options
are the output options.
options.chunkFilename
is the filename under that chunks are expected.
LibraryTemplatePlugin(name, target)
The entries chunks are decorated to form a library name
of type type
.
webworker/WebWorkerTemplatePlugin(options)
Chunks are loaded by importScripts
. Else it's similar to JsonpTemplatePlugin
.
options
are the output options.
Decorates the module template by wrapping each module in a eval
annotated with // @sourceURL
.
SourceMapDevToolPlugin(sourceMapFilename, sourceMappingURLComment, moduleFilenameTemplate, fallbackModuleFilenameTemplate)
Decorates the templates by generating a SourceMap for each chunk.
sourceMapFilename
the filename template of the SourceMap. [hash]
, [name]
, [id]
, [file]
and [filebase]
are replaced. If this argument is missing, the SourceMap will be inlined as DataUrl.
HotModuleReplacementPlugin(options)
Add support for hot module replacement. Decorates the templates to add runtime code. Adds module.hot
API.
options.hotUpdateChunkFilename
the filename for hot update chunks.
options.hotUpdateMainFilename
the filename for the hot update manifest.
options.hotUpdateFunction
JSON function name for the hot update.
Plugins affecting the source code of modules.
Make webpack_public_path, webpack_require, webpack_modules and webpack_chunk_load accessible. Ensures that require.valueOf
and require.onError
are not processed by other plugins.
Currently useless. Ensures compatibility with other module loaders.
Tries to evaluate expressions in if (...)
statements and ternaries to replace them with true
/false
for further possible dead branch elimination using hooks fired by the parser.
There are multiple optimizations in production mode regarding dead branches:
Webpack will try to evaluate conditional statements. If it succeeds then the dead branch is removed. Webpack can't do constant folding unless the compiler knows it. For example:
import { calculateTax } from './tax';
const FOO = 1;
if (FOO === 0) {
// dead branch
calculateTax();
}
In the above example, webpack is unable to prune the branch, but Terser does. However, if FOO
is defined using DefinePlugin, webpack will succeed.
It is important to mention that import { calculateTax } from './tax';
will also get pruned because calculateTax()
call was in the dead branch and got eliminated.
ProvidePlugin(name, request)
If name
is used in a module it is filled by a module loaded by require(<request>)
.
NodeStuffPlugin(options, context)
Provide stuff that is normally available in Node.js modules.
It also ensures that module
is filled with some Node.js stuff if you use it.
Provide stuff that is normally available in require.js.
require[js].config
is removed. require.version
is 0.0.0
. requirejs.onError
is mapped to require.onError
.
node/NodeSourcePlugin(options)
This module adds stuff from Node.js that is not available in non Node.js environments.
It adds polyfills for process
, console
, Buffer
and global
if used. It also binds the built in Node.js replacement modules.
node/NodeTargetPlugin()
The plugins should be used if you run the bundle in a Node.js environment.
If ensures that native modules are loaded correctly even if bundled.
dependencies/AMDPlugin(options)
Provides AMD-style define
and require
to modules. Also bind require.amd
, define.amd
and webpack_amd_options## to the options
passed as parameter.
dependencies/CommonJsPlugin
Provides CommonJs-style require
to modules.
dependencies/RequireContextPlugin(modulesDirectories, extensions)
Provides require.context
. The parameter modulesDirectories
and extensions
are used to find alternative requests for files. It's useful to provide the same arrays as you provide to the resolver.
dependencies/RequireEnsurePlugin()
Provides require.ensure
.
dependencies/RequireIncludePlugin()
Provides require.include
.
DefinePlugin(definitions)
Define constants for identifier.
definitions
is an object.
Note that all plugins under webpack.optimize
namespace should only be used when mode
set to 'none'
. Otherwise you might get into trouble where plugins are applied twice.
optimize/LimitChunkCountPlugin(options)
Merge chunks limit chunk count is lower than options.maxChunks
.
The overhead for each chunks is provided by options.chunkOverhead
or defaults to 10000. Entry chunks sizes are multiplied by options.entryChunkMultiplicator
(or 10).
Chunks that reduce the total size the most are merged first. If multiple combinations are equal the minimal merged size wins.
optimize/MergeDuplicateChunksPlugin()
Chunks with the same modules are merged.
optimize/RemoveEmptyChunksPlugin()
Modules that are included in every parent chunk are removed from the chunk.
optimize/MinChunkSizePlugin(minChunkSize)
Merges chunks until each chunk has the minimum size of minChunkSize
.
See the ModuleConcatenationPlugin page for details.
optimize/FlagIncludedChunksPlugin()
Adds chunk ids of chunks which are included in the chunk. This eliminates unnecessary chunk loads.
optimize/RealContentHashPlugin()
When optimization.realContentHash
option is enabled, webpack will apply RealContentHashPlugin
to compiler internally.
RealContentHashPlugin
provides a updateHash
5.8.0+ hook for customizing hash updating:
const webpack = require('webpack');
const RealContentHashPlugin = webpack.optimize.RealContentHashPlugin;
// ...
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
const hooks = RealContentHashPlugin.getCompilationHooks(compilation);
hooks.updateHash.tap('MyPlugin', (content, oldHash) => {
// you can calculate the hash here as you wish
});
});
This plugin uses JSON.stringify() to minify your JSON.
To begin, you'll need to install json-minimizer-webpack-plugin
:
npm install json-minimizer-webpack-plugin --save-dev
or
yarn add -D json-minimizer-webpack-plugin
or
pnpm add -D json-minimizer-webpack-plugin
Then add the plugin to your webpack
configuration. For example:
webpack.config.js
const JsonMinimizerPlugin = require("json-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.json$/i,
type: "asset/resource",
},
],
},
plugins: [
new CopyPlugin({
patterns: [
{
context: path.resolve(__dirname, "dist"),
from: "./src/*.json",
},
],
}),
],
optimization: {
minimize: true,
minimizer: [
// For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
// `...`
new JsonMinimizerPlugin(),
],
},
};
And run webpack
via your preferred method.
test
Type:
type test = string | RegExp | Array<string | RegExp>;
Default: /\.json(\?.*)?$/i
Test to match files against.
module.exports = {
optimization: {
minimize: true,
minimizer: [
new JsonMinimizerPlugin({
test: /\.foo\.json/i,
}),
],
},
};
include
Type:
type include = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to include.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new JsonMinimizerPlugin({
include: /\/includes/,
}),
],
},
};
exclude
Type:
type exclude = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to exclude.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new JsonMinimizerPlugin({
exclude: /\/excludes/,
}),
],
},
};
minimizerOptions
Type:
type minimizerOptions = {
space?: null | string | number;
replacer?: null | Function | Array<string | number>;
};
Default: { replacer: null, space: null }
JSON.stringify()
options.
module.exports = {
optimization: {
minimize: true,
minimizer: [
new JsonMinimizerPlugin({
minimizerOptions: {
space: "\t",
},
}),
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
While writing your code, you may have already added many code split points to load stuff on demand. After compiling you might notice that some chunks are too small - creating larger HTTP overhead. LimitChunkCountPlugin
can post-process your chunks by merging them.
new webpack.optimize.LimitChunkCountPlugin({
// Options...
});
The following options are supported:
number
Limit the maximum number of chunks using a value greater than or equal to 1
. Using 1
will prevent any additional chunks from being added as the entry/main chunk is also included in the count.
webpack.config.js
const webpack = require('webpack');
module.exports = {
// ...
plugins: [
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 5,
}),
],
};
Keeping chunk size above the specified limit is no longer a feature of this plugin. Use MinChunkSizePlugin instead.
This plugin and it's options can also be invoked via the CLI:
webpack --optimize-max-chunks 15
Keep chunk size above the specified limit by merging chunks that are smaller than the minChunkSize
.
new webpack.optimize.MinChunkSizePlugin({
minChunkSize: 10000, // Minimum number of characters
});
This plugin and it's options can also be invoked via the CLI:
webpack --optimize-min-chunk-size 10000
This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps.
It builds on top of a new webpack v5 feature and requires webpack 5 to work.
Compared to the extract-text-webpack-plugin:
To begin, you'll need to install mini-css-extract-plugin
:
npm install --save-dev mini-css-extract-plugin
or
yarn add -D mini-css-extract-plugin
or
pnpm add -D mini-css-extract-plugin
It's recommended to combine mini-css-extract-plugin
with the css-loader
Then add the loader and the plugin to your webpack
config. For example:
style.css
body {
background: green;
}
component.js
import "./style.css";
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
[!WARNING]
Note that if you import CSS from your webpack entrypoint or import styles in the initial chunk,
mini-css-extract-plugin
will not load this CSS into the page. Please usehtml-webpack-plugin
for automatic generationlink
tags or createindex.html
file withlink
tag.
[!WARNING]
Source maps works only for
source-map
/nosources-source-map
/hidden-nosources-source-map
/hidden-source-map
values because CSS only supports source maps with thesourceMappingURL
comment (i.e.//# sourceMappingURL=style.css.map
). If you need setdevtool
to another value you can enable source maps generation for extracted CSS usingsourceMap: true
forcss-loader
.
filename
Type:
type filename =
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
Default: [name].css
This option determines the name of each output CSS file.
Works like output.filename
chunkFilename
Type:
type chunkFilename =
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
Default: based on filename
Specifying
chunkFilename
as afunction
is only available in webpack@5
This option determines the name of non-entry chunk files.
Works like output.chunkFilename
ignoreOrder
Type:
type ignoreOrder = boolean;
Default: false
Remove Order Warnings. See examples below for details.
insert
Type:
type insert = string | ((linkTag: HTMLLinkElement) => void);
Default: document.head.appendChild(linkTag);
Inserts the link
tag at the given position for non-initial (async) CSS chunks
[!WARNING]
Only for non-initial (async) chunks.
By default, the mini-css-extract-plugin
appends styles (<link>
elements) to document.head
of the current window
.
However in some circumstances it might be necessary to have finer control over the append target or even delay link
elements insertion.
For example this is the case when you asynchronously load styles for an application that runs inside of an iframe.
In such cases insert
can be configured to be a function or a custom selector.
If you target an iframe make sure that the parent document has sufficient access rights to reach into the frame document and append elements to it.
string
Allows to setup custom query selector.
A new <link>
element will be inserted after the found item.
webpack.config.js
new MiniCssExtractPlugin({
insert: "#some-element",
});
A new <link>
element will be inserted after the element with id some-element
.
function
Allows to override default behavior and insert styles at any position.
⚠ Do not forget that this code will run in the browser alongside your application. Since not all browsers support latest ECMA features like
let
,const
,arrow function expression
and etc we recommend you to use only ECMA 5 features and syntax.
⚠ The
insert
function is serialized to string and passed to the plugin. This means that it won't have access to the scope of the webpack configuration module.
webpack.config.js
new MiniCssExtractPlugin({
insert: function (linkTag) {
var reference = document.querySelector("#some-element");
if (reference) {
reference.parentNode.insertBefore(linkTag, reference);
}
},
});
A new <link>
element will be inserted before the element with id some-element
.
attributes
Type:
type attributes = Record<string, string>};
Default: {}
[!WARNING]
Only for non-initial (async) chunks.
If defined, the mini-css-extract-plugin
will attach given attributes with their values on <link>
element.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
attributes: {
id: "target",
"data-target": "example",
},
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
[!NOTE]
It's only applied to dynamically loaded css chunks, if you want to modify link attributes inside html file, please using html-webpack-plugin
linkType
Type:
type linkType = string | boolean;
Default: text/css
This option allows loading asynchronous chunks with a custom link type, such as <link type="text/css" ...>
.
string
Possible values: text/css
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
linkType: "text/css",
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
boolean
false
disables the link type
attribute
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
linkType: false,
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
runtime
Type:
type runtime = boolean;
Default: true
Allows to enable/disable the runtime generation. CSS will be still extracted and can be used for a custom loading methods. For example, you can use assets-webpack-plugin to retrieve them then use your own runtime code to download assets when needed.
false
to skip.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
runtime: false,
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
experimentalUseImportModule
Type:
type experimentalUseImportModule = boolean;
Default: undefined
Enabled by default if not explicitly enabled (i.e. true
and false
allow you to explicitly control this option) and new API is available (at least webpack 5.52.0
is required).
Boolean values are available since version 5.33.2
, but you need to enable experiments.executeModule
(not required from webpack 5.52.0
).
Use a new webpack API to execute modules instead of child compilers. This improves performance and memory usage a lot.
When combined with experiments.layers
, this adds a layer
option to the loader options to specify the layer of the css execution.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// You don't need this for `>= 5.52.0` due to the fact that this is enabled by default
// Required only for `>= 5.33.2 & <= 5.52.0`
// Not available/unsafe for `<= 5.33.2`
experimentalUseImportModule: true,
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
publicPath
Type:
type publicPath =
| string
| ((resourcePath: string, rootContext: string) => string);
Default: the publicPath
in webpackOptions.output
Specifies a custom public path for the external resources like images, files, etc inside CSS
.
Works like output.publicPath
string
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "[name].css",
chunkFilename: "[id].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "/public/path/to/",
},
},
"css-loader",
],
},
],
},
};
function
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "[name].css",
chunkFilename: "[id].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: (resourcePath, context) => {
return path.relative(path.dirname(resourcePath), context) + "/";
},
},
},
"css-loader",
],
},
],
},
};
emit
Type:
type emit = boolean;
Default: true
If true, emits a file (writes a file to the filesystem). If false, the plugin will extract the CSS but will not emit the file. It is often useful to disable this option for server-side packages.
esModule
Type:
type esModule = boolean;
Default: true
By default, mini-css-extract-plugin
generates JS modules that use the ES modules syntax.
There are some cases in which using ES modules is beneficial, like in the case of module concatenation and tree shaking.
You can enable a CommonJS syntax using:
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
esModule: false,
},
},
"css-loader",
],
},
],
},
};
defaultExport
Type:
type defaultExport = boolean;
Default: false
[!NOTE]
This option will work only when you set
namedExport
totrue
incss-loader
By default, mini-css-extract-plugin
generates JS modules based on the esModule
and namedExport
options in css-loader
.
Using the esModule
and namedExport
options will allow you to better optimize your code.
If you set esModule: true
and namedExport: true
for css-loader
mini-css-extract-plugin
will generate only a named export.
Our official recommendation is to use only named export for better future compatibility.
But for some applications, it is not easy to quickly rewrite the code from the default export to a named export.
In case you need both default and named exports, you can enable this option:
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
defaultExport: true,
},
},
{
loader: "css-loader",
options: {
esModule: true,
modules: {
namedExport: true,
},
},
},
],
},
],
},
};
For production
builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on.
This can be achieved by using the mini-css-extract-plugin
, because it creates separate css files.
For development
mode (including webpack-dev-server
) you can use style-loader, because it injects CSS into the DOM using multiple and works faster.
Do not use
style-loader
andmini-css-extract-plugin
together.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";
module.exports = {
module: {
rules: [
{
// If you enable `experiments.css` or `experiments.futureDefaults`, please uncomment line below
// type: "javascript/auto",
test: /\.(sa|sc|c)ss$/,
use: [
devMode ? "style-loader" : MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader",
],
},
],
},
plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// all options are optional
filename: "[name].css",
chunkFilename: "[id].css",
ignoreOrder: false, // Enable to remove warnings about conflicting order
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// you can specify a publicPath here
// by default it uses publicPath in webpackOptions.output
publicPath: "../",
},
},
"css-loader",
],
},
],
},
};
⚠ Names of locals are converted to
camelCase
.
⚠ It is not allowed to use JavaScript reserved words in css class names.
⚠ Options
esModule
andmodules.namedExport
incss-loader
should be enabled.
styles.css
.foo-baz {
color: red;
}
.bar {
color: blue;
}
index.js
import { fooBaz, bar } from "./styles.css";
console.log(fooBaz, bar);
You can enable a ES module named export using:
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: "css-loader",
options: {
esModule: true,
modules: {
namedExport: true,
localIdentName: "foo__[name]__[local]",
},
},
},
],
},
],
},
};
publicPath
option as functionwebpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "[name].css",
chunkFilename: "[id].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: (resourcePath, context) => {
// publicPath is the relative path of the resource to the context
// e.g. for ./css/admin/main.css the publicPath will be ../../
// while for ./css/main.css the publicPath will be ../
return path.relative(path.dirname(resourcePath), context) + "/";
},
},
},
"css-loader",
],
},
],
},
};
This plugin should not be used with style-loader
in the loaders chain.
Here is an example to have both HMR in development
and your styles extracted in a file for production
builds.
(Loaders options left out for clarity, adapt accordingly to your needs.)
You should not use HotModuleReplacementPlugin
plugin if you are using a webpack-dev-server
.
webpack-dev-server
enables / disables HMR using hot
option.
webpack.config.js
const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";
const plugins = [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: devMode ? "[name].css" : "[name].[contenthash].css",
chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
}),
];
if (devMode) {
// only enable hot in development
plugins.push(new webpack.HotModuleReplacementPlugin());
}
module.exports = {
plugins,
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader",
],
},
],
},
};
[!NOTE]
HMR is automatically supported in webpack 5. No need to configure it. Skip the following:
The mini-css-extract-plugin
supports hot reloading of actual css files in development.
Some options are provided to enable HMR of both standard stylesheets and locally scoped CSS or CSS modules.
Below is an example configuration of mini-css for HMR use with CSS modules.
You should not use HotModuleReplacementPlugin
plugin if you are using a webpack-dev-server
.
webpack-dev-server
enables / disables HMR using hot
option.
webpack.config.js
const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const plugins = [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: devMode ? "[name].css" : "[name].[contenthash].css",
chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
}),
];
if (devMode) {
// only enable hot in development
plugins.push(new webpack.HotModuleReplacementPlugin());
}
module.exports = {
plugins,
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {},
},
"css-loader",
],
},
],
},
};
To minify the output, use a plugin like css-minimizer-webpack-plugin.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
optimization: {
minimizer: [
// For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
// `...`,
new CssMinimizerPlugin(),
],
},
};
This will enable CSS optimization only in production mode. If you want to run it also in development set the optimization.minimize
option to true.
The runtime code detects already added CSS via <link>
or <style>
tag.
This can be useful when injecting CSS on server-side for Server-Side-Rendering.
The href
of the <link>
tag has to match the URL that will be used for loading the CSS chunk.
The data-href
attribute can be used for <link>
and <style>
too.
When inlining CSS data-href
must be used.
The CSS can be extracted in one CSS file using optimization.splitChunks.cacheGroups
.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: "styles",
type: "css/mini-extract",
chunks: "all",
enforce: true,
},
},
},
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
Note that type
should be used instead of test
in Webpack 5, or else an extra .js
file can be generated besides the .css
file. This is because test
doesn't know which modules should be dropped (in this case, it won't detect that .js
should be dropped).
You may also extract the CSS based on the webpack entry name. This is especially useful if you import routes dynamically but want to keep your CSS bundled according to entry. This also prevents the CSS duplication issue one had with the ExtractTextPlugin.
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
foo: path.resolve(__dirname, "src/foo"),
bar: path.resolve(__dirname, "src/bar"),
},
optimization: {
splitChunks: {
cacheGroups: {
fooStyles: {
type: "css/mini-extract",
name: "styles_foo",
chunks: (chunk) => {
return chunk.name === "foo";
},
enforce: true,
},
barStyles: {
type: "css/mini-extract",
name: "styles_bar",
chunks: (chunk) => {
return chunk.name === "bar";
},
enforce: true,
},
},
},
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
With the filename
option you can use chunk data to customize the filename.
This is particularly useful when dealing with multiple entry points and wanting to get more control out of the filename for a given entry point/chunk.
In the example below, we'll use filename
to output the generated css into a different directory.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: ({ chunk }) => `${chunk.name.replace("/js/", "/css/")}.css`,
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
For long term caching use filename: "[contenthash].css"
. Optionally add [name]
.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
chunkFilename: "[id].[contenthash].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
For projects where css ordering has been mitigated through consistent use of scoping or naming conventions, such as CSS Modules, the css order warnings can be disabled by setting the ignoreOrder flag to true for the plugin.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
ignoreOrder: true,
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/index.js",
module: {
rules: [
{
test: /\.s[ac]ss$/i,
oneOf: [
{
resourceQuery: "?dark",
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "sass-loader",
options: {
additionalData: `@use 'dark-theme/vars' as vars;`,
},
},
],
},
{
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "sass-loader",
options: {
additionalData: `@use 'light-theme/vars' as vars;`,
},
},
],
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
attributes: {
id: "theme",
},
}),
],
};
src/index.js
import "./style.scss";
let theme = "light";
const themes = {};
themes[theme] = document.querySelector("#theme");
async function loadTheme(newTheme) {
// eslint-disable-next-line no-console
console.log(`CHANGE THEME - ${newTheme}`);
const themeElement = document.querySelector("#theme");
if (themeElement) {
themeElement.remove();
}
if (themes[newTheme]) {
// eslint-disable-next-line no-console
console.log(`THEME ALREADY LOADED - ${newTheme}`);
document.head.appendChild(themes[newTheme]);
return;
}
if (newTheme === "dark") {
// eslint-disable-next-line no-console
console.log(`LOADING THEME - ${newTheme}`);
import(/* webpackChunkName: "dark" */ "./style.scss?dark").then(() => {
themes[newTheme] = document.querySelector("#theme");
// eslint-disable-next-line no-console
console.log(`LOADED - ${newTheme}`);
});
}
}
document.onclick = () => {
if (theme === "light") {
theme = "dark";
} else {
theme = "light";
}
loadTheme(theme);
};
src/dark-theme/_vars.scss
$background: black;
src/light-theme/_vars.scss
$background: white;
src/styles.scss
body {
background-color: vars.$background;
}
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Document</title>
<link id="theme" rel="stylesheet" type="text/css" href="./main.css" />
</head>
<body>
<script src="./main.js"></script>
</body>
</html>
If you'd like to extract the media queries from the extracted CSS (so mobile users don't need to load desktop or tablet specific CSS anymore) you should use one of the following plugins:
The mini-css-extract-plugin provides hooks to extend it to your needs.
SyncWaterfallHook
Called before inject the insert code for link tag. Should return a string
MiniCssExtractPlugin.getCompilationHooks(compilation).beforeTagInsert.tap(
"changeHref",
(source, varNames) =>
Template.asString([
source,
`${varNames.tag}.setAttribute("href", "/plugins/mini-css-extract-plugin/));`,
])
);
Please take a moment to read our contributing guidelines if you haven't yet done so.
In the past, one of webpack’s trade-offs when bundling was that each module in your bundle would be wrapped in individual function closures. These wrapper functions made it slower for your JavaScript to execute in the browser. In comparison, tools like Closure Compiler and RollupJS ‘hoist’ or concatenate the scope of all your modules into one closure and allow for your code to have a faster execution time in the browser.
This plugin will enable the same concatenation behavior in webpack. By default this plugin is already enabled in production mode
and disabled otherwise. If you need to override the production mode
optimization, set the optimization.concatenateModules
option to false
. To enable concatenation behavior in other modes, you can add ModuleConcatenationPlugin
manually or use the optimization.concatenateModules
option:
new webpack.optimize.ModuleConcatenationPlugin();
This concatenation behavior is called “scope hoisting.”
Scope hoisting is specifically a feature made possible by ECMAScript Module syntax. Because of this webpack may fallback to normal bundling based on what kind of modules you are using, and other conditions.
As the article explains, webpack attempts to achieve partial scope hoisting. It will merge modules into a single scope but cannot do so in every case. If webpack cannot merge a module, the two alternatives are Prevent and Root. Prevent means the module must be in its own scope. Root means a new module group will be created. The following conditions determine the outcome:
Condition | Outcome |
---|---|
Non ES6 Module | Prevent |
Imported By Non Import | Root |
Imported From Other Chunk | Root |
Imported By Multiple Other Module Groups | Root |
Imported With import() | Root |
Affected By ProvidePlugin Or Using module | Prevent |
HMR Accepted | Root |
Using eval() | Prevent |
In Multiple Chunks | Prevent |
export * from "cjs-module" | Prevent |
The following pseudo JavaScript explains the algorithm:
modules.forEach((module) => {
const group = new ModuleGroup({
root: module,
});
module.dependencies.forEach((dependency) => {
tryToAdd(group, dependency);
});
if (group.modules.length > 1) {
orderedModules = topologicalSort(group.modules);
concatenatedModule = new ConcatenatedModule(orderedModules);
chunk.add(concatenatedModule);
orderedModules.forEach((groupModule) => {
chunk.remove(groupModule);
});
}
});
function tryToAdd(group, module) {
if (group.has(module)) {
return true;
}
if (!hasPreconditions(module)) {
return false;
}
const nextGroup = group;
const result = module.dependents.reduce((check, dependent) => {
return check && tryToAdd(nextGroup, dependent);
}, true);
if (!result) {
return false;
}
module.dependencies.forEach((dependency) => {
tryToAdd(group, dependency);
});
group.merge(nextGroup);
return true;
}
When using the webpack CLI, the --stats-optimization-bailout
flag will display bailout reasons. When using the webpack config, add the following to the stats
object:
module.exports = {
//...
stats: {
// Display bailout reasons
optimizationBailout: true,
},
};
Webpack has a rich plugin interface. Most of the features within webpack itself use this plugin interface. This makes webpack flexible.
Name | Description |
---|---|
BannerPlugin | Add a banner to the top of each generated chunk |
ChunksWebpackPlugin | Create HTML files with entrypoints and chunks relations to serve your bundles |
CommonsChunkPlugin | Extract common modules shared between chunks |
CompressionWebpackPlugin | Prepare compressed versions of assets to serve them with Content-Encoding |
ContextReplacementPlugin | Override the inferred context of a require expression |
CopyWebpackPlugin | Copies individual files or entire directories to the build directory |
DefinePlugin | Allow global constants configured at compile time |
DllPlugin | Split bundles in order to drastically improve build time |
EnvironmentPlugin | Shorthand for using the DefinePlugin on process.env keys |
EslintWebpackPlugin | A ESLint plugin for webpack |
HotModuleReplacementPlugin | Enable Hot Module Replacement (HMR) |
HtmlWebpackPlugin | Easily create HTML files to serve your bundles |
IgnorePlugin | Exclude certain modules from bundles |
LimitChunkCountPlugin | Set min/max limits for chunking to better control chunking |
MinChunkSizePlugin | Keep chunk size above the specified limit |
MiniCssExtractPlugin | creates a CSS file per JS file which requires CSS |
NoEmitOnErrorsPlugin | Skip the emitting phase when there are compilation errors |
NormalModuleReplacementPlugin | Replace resource(s) that matches a regexp |
NpmInstallWebpackPlugin | Auto-install missing dependencies during development |
ProgressPlugin | Report compilation progress |
ProvidePlugin | Use modules without having to use import/require |
SourceMapDevToolPlugin | Enables a more fine grained control of source maps |
EvalSourceMapDevToolPlugin | Enables a more fine grained control of eval source maps |
SvgChunkWebpackPlugin | Generate SVG sprites optimized by SVGO based on your entry point dependencies |
TerserPlugin | Uses Terser to minify the JS in your project |
For more third-party plugins, see the list from awesome-webpack.
The ModuleFederationPlugin
allows a build to provide or consume modules with other independent builds at runtime.
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
// options' typings in typescript
runtime: string | false,
}),
],
};
Create a new runtime chunk with the specified name.
webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
runtime: 'my-runtime-name',
}),
],
};
With the shared
key in the configuration you can define libraries that are shared between your federated modules. The package name is the same as the one found in the dependencies
section of your package.json. However, by default webpack will only share the root level of a library.
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
// adds date-fns as shared module
shared: ['date-fns'],
}),
],
};
So in your application you could do something like
import { format } from 'date-fns';
format(new Date(2014, 1, 11), 'MM/dd/yyyy');
and webpack will automatically share date-fns
between all your federated modules that define date-fns
as a shared library.
However, if you want to access something that is not located at the root level of the package, for example date-fns/locale/en-GB/index.js
, you need to append /
to the package name in your shared
configuration:
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
// adds date-fns as shared module
// all files of the package will be shared
shared: ['date-fns/'],
}),
],
};
The /
syntax allows you to access all files of a package. However, it should be used only where necessary, because it has an impact on performance especially in development
mode.
There are three ways to specify the versions of shared libraries.
This syntax allows you to share libraries with package name only. This approach is good for prototyping, but it will not allow you to scale to large production environment given that libraries like react
and react-dom
will require additional requirements.
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
// adds lodash as shared module
// version is inferred from package.json
// there is no version check for the required version
// so it will always use the higher version found
shared: ['lodash'],
}),
],
};
This syntax provides you more control over each shared library in which you can define package name as the key and version (semver) as the value.
module.exports = {
plugins: [
new ModuleFederationPlugin({
shared: {
// adds lodash as shared module
// version is inferred from package.json
// it will use the highest lodash version that is >= 4.17 and < 5
lodash: '^4.17.0',
},
}),
],
};
This syntax allows you to provide additional hints to each shared package where you define the package name as the key, and the value as an object containing hints to modify sharing behavior.
const deps = require('./package.json').dependencies;
module.exports = {
plugins: [
new ModuleFederationPlugin({
shared: {
// adds react as shared module
react: {
requiredVersion: deps.react,
singleton: true,
},
},
}),
],
};
eager
boolean
This hint will allow webpack to include the provided and fallback module directly instead of fetching the library via an asynchronous request. In other words, this allows to use this shared module in the initial chunk. Also, be careful that all provided and fallback modules will always be downloaded when this hint is enabled.
import
false | string
The provided module that should be placed in the shared scope. This provided module also acts as fallback module if no shared module is found in the shared scope or version isn't valid. (The value for this hint defaults to the property name.)
packageName
string
The package name that is used to determine required version from description file. This is only needed when the package name can't be automatically determined from request.
requiredVersion
false
string
This field specifies the required version of the package. It accepts semantic versioning, such as "^1.2.3". Additionally, it retrieves the version if it's provided as a URL, for instance: "git+ssh://git@github.com:foo/bar.git#v1.0.0".
shareKey
string
The requested shared module is looked up under this key from the shared scope.
shareScope
string
The name of the shared scope.
singleton
boolean
This hint only allows a single version of the shared module in the shared scope (disabled by default). Some libraries use a global internal state (e.g. react, react-dom). Thus, it is critical to have only one instance of the library running at a time.
In cases where there are multiple versions of the same dependency in the shared scope, the highest semantic version is used.
strictVersion
boolean
This hint allows webpack to reject the shared module if version is not valid (defaults to true
when local fallback module is available and shared module is not a singleton, otherwise false
, it has no effect if there is no required version specified). Throws a runtime error if the required version is not found.
version
false | string
The version of the provided module. It allows webpack to replace lower matching versions, but not higher.
By default, webpack uses the version from the package.json
file of the dependency.
module.exports = {
plugins: [
new ModuleFederationPlugin({
// adds vue as shared module
// version is inferred from package.json
// it will always use the shared version, but print a warning when the shared vue is < 2.6.5 or >= 3
shared: {
vue: {
requiredVersion: '^2.6.5',
singleton: true,
},
},
}),
],
};
module.exports = {
plugins: [
new ModuleFederationPlugin({
// adds vue as shared module
// there is no local version provided
// it will emit a warning if the shared vue is < 2.6.5 or >= 3
shared: {
vue: {
import: false,
requiredVersion: '^2.6.5',
},
},
}),
],
};
module.exports = {
plugins: [
new ModuleFederationPlugin({
// adds vue as shared module
// there is no local version provided
// it will throw an error when the shared vue is < 2.6.5 or >= 3
shared: {
vue: {
import: false,
requiredVersion: '^2.6.5',
strictVersion: true,
},
},
}),
],
};
module.exports = {
plugins: [
new ModuleFederationPlugin({
shared: {
'my-vue': {
// can be referenced by import "my-vue"
import: 'vue', // the "vue" package will be used as a provided and fallback module
shareKey: 'shared-vue', // under this name the shared module will be placed in the share scope
shareScope: 'default', // share scope with this name will be used
singleton: true, // only a single version of the shared module is allowed
strictVersion: true, // don't use shared version when version isn't valid. Singleton or modules without fallback will throw, otherwise fallback is used
version: '1.2.3', // the version of the shared module
requiredVersion: '^1.0.0', // the required version of the shared module
},
},
}),
],
};
The NoEmitOnErrorsPlugin
allows you to avoid emitting assets when there are any errors. Enabled by default, you can disable using optimization.emitOnErrors
webpack.config.js
module.exports = {
plugins: [new webpack.NoEmitOnErrorsPlugin()],
};
The NormalModuleReplacementPlugin
allows you to replace resources that match resourceRegExp
with newResource
. If newResource
is relative, it is resolved relative to the previous resource. If newResource
is a function, it is expected to overwrite the request attribute of the supplied resource.
This can be useful for allowing different behaviour between builds.
new webpack.NormalModuleReplacementPlugin(resourceRegExp, newResource);
Note that the resourceRegExp
is tested against the request you write in your code, not the resolved resource. For instance, './sum'
will be used to test instead of './sum.js'
when you have code import sum from './sum'
.
Also please note that when using Windows, you have to accomodate for the different folder separator symbol. E.g. /src\/environments\/environment\.ts/
won't work on Windows, you have to use /src[\\/]environments[\\/]environment\.ts/,
instead.
Replace a specific module when building for a development environment.
Say you have a configuration file some/path/config.development.module.js
and a special version for production in some/path/config.production.module.js
Add the following plugin when building for production:
new webpack.NormalModuleReplacementPlugin(
/some\/path\/config\.development\.js/,
'./config.production.js'
);
Conditional build depending on an specified environment.
Say you want a configuration with specific values for different build targets.
module.exports = function (env) {
var appTarget = env.APP_TARGET || 'VERSION_A';
return {
plugins: [
new webpack.NormalModuleReplacementPlugin(/-APP_TARGET$/, function (
resource
) {
resource.request = resource.request.replace(
/-APP_TARGET/,
`-${appTarget}`
);
if (resource.createData) {
resource.createData.request = resource.request;
}
}),
],
};
};
Create the two configuration files:
app/config-VERSION_A.js
export default {
title: 'I am version A',
};
app/config-VERSION_B.js
export default {
title: 'I am version B',
};
Then import that configuration using the keyword you're looking for in the regexp:
import config from 'app/config-APP_TARGET';
console.log(config.title);
And now you get the right configuration imported depending on which target you're building for:
npx webpack --env APP_TARGET=VERSION_A
=> 'I am version A'
npx webpack --env APP_TARGET=VERSION_B
=> 'I am version B'
Prefetch normal module requests, causing them to be resolved and built before the first import
or require
of that module occurs. Using this plugin can boost performance. Try to profile the build first to determine clever prefetching points.
new webpack.PrefetchPlugin([context], request);
context
: An absolute path to a directoryrequest
: A request string for a normal moduleGenerate Chrome profile file which includes timings of plugins execution. Outputs events.json
file by default. It is possible to provide custom file path using outputPath
option.
Note : ProfilingPlugin accepts only absolute paths.
outputPath
: An absolute path to a custom output file (json)new webpack.debug.ProfilingPlugin();
outputPath
new webpack.debug.ProfilingPlugin({
outputPath: path.join(__dirname, 'profiling/profileEvents.json'),
});
In order to view the profile file:
ProfilingPlugin
.Performance
tab (formerly Timeline
).events.json
by default) into the profiler.It will then display timeline stats and calls per plugin!
The ProgressPlugin
provides a way to customize how progress is reported during a compilation.
Create an instance of ProgressPlugin
and provide one of the allowed params, besides, there's a static method createDefaultHandler
which can be used to customize the default handler.
function
Provide a handler function which will be called when hooks report progress. handler
function arguments:
percentage
: a number between 0 and 1 indicating the completion percentage of the compilationmessage
: a short description of the currently-executing hook...args
: zero or more additional strings describing the current progressconst handler = (percentage, message, ...args) => {
// e.g. Output each progress message directly to the console:
console.info(percentage, message, ...args);
};
new webpack.ProgressPlugin(handler);
object
When providing an object
to the ProgressPlugin
, following properties are supported:
activeModules
(boolean = false
): Shows active modules count and one active module in progress message.entries
(boolean = true
): Shows entries count in progress message.handler
(See Providing function)modules
(boolean = true
): Shows modules count in progress message.modulesCount
(number = 5000
): A minimum modules count to start with. Takes effect when modules
property is enabled.profile
(boolean = false
): Tells ProgressPlugin
to collect profile data for progress steps.dependencies
(boolean = true
): Shows the count of dependencies in progress message.dependenciesCount
(number = 10000
): A minimum dependencies count to start with. Takes effect when dependencies
property is enabled.percentBy
(string = null: 'entries' | 'dependencies' | 'modules' | null
): Tells ProgressPlugin
how to calculate progress percentage.new webpack.ProgressPlugin({
activeModules: false,
entries: true,
handler(percentage, message, ...args) {
// custom logic
},
modules: true,
modulesCount: 5000,
profile: false,
dependencies: true,
dependenciesCount: 10000,
percentBy: null,
});
If the default handler of ProgressPlugin
does not meet your requirements, you can customize it using the static ProgressPlugin.createDefaultHandler
method.
static createDefaultHandler: (
profile: undefined | null | boolean,
logger: WebpackLogger
) => (percentage: number, msg: string, ...args: string[]) => void;
By default, progress percentage is calculated based on built modules count and total modules count: built / total
The total modules count is unknown in advance and changes during the build. This may cause inaccurate progress percentage.
To solve this problem ProgressPlugin
caches the last known total modules count and reuses this value on the next build. The first build will warm the cache but the following builds will use and update this value.
We recommend using
percentBy: 'entries'
setting for projects with multiple configured entry points. Percentage calculation will become more accurate because the amount of entry points is known in advance.
The following hooks report progress information to ProgressPlugin
.
Compiler
Compilation
Automatically load modules instead of having to import
or require
them everywhere.
new webpack.ProvidePlugin({
identifier: 'module1',
// ...
});
or
new webpack.ProvidePlugin({
identifier: ['module1', 'property1'],
// ...
});
By default, module resolution path is current folder (./**)
and node_modules
.
It is also possible to specify full path:
const path = require('path');
new webpack.ProvidePlugin({
identifier: path.resolve(path.join(__dirname, 'src/module1')),
// ...
});
Whenever the identifier
is encountered as free variable in a module, the module
is loaded automatically and the identifier
is filled with the exports of the loaded module
(or property
in order to support named exports).
For importing the default export of an ES2015 module, you have to specify the default property of module.
To automatically load jquery
we can point both variables it exposes to the corresponding node module:
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
});
Then in any of our source code:
// in a module
$('#item'); // <= works
jQuery('#item'); // <= also works
// $ is automatically set to the exports of module "jquery"
Angular looks for window.jQuery
in order to determine whether jQuery is present, see the source code.
new webpack.ProvidePlugin({
'window.jQuery': 'jquery',
});
new webpack.ProvidePlugin({
_map: ['lodash', 'map'],
});
new webpack.ProvidePlugin({
Vue: ['vue/dist/vue.esm.js', 'default'],
});
This plugin enables more fine grained control of source map generation. It is also enabled automatically by certain settings of the devtool
configuration option.
new webpack.SourceMapDevToolPlugin(options);
The following options are supported:
test
(string
RegExp
[string, RegExp]
): Include source maps for modules based on their extension (defaults to .js
, .mjs
, and .css
).
include
(string
RegExp
[string, RegExp]
): Include source maps for module paths that match the given value.
exclude
(string
RegExp
[string, RegExp]
): Exclude modules that match the given value from source map generation.
filename
(string
): Defines the output filename of the SourceMap (will be inlined if no value is provided).
append
(string
function
false
): Appends the given value to the original asset. Usually the #sourceMappingURL
comment. [url]
is replaced with a URL to the source map file. Since webpack v4.36.0, path parameters are supported: [chunk]
, [filename]
and [contenthash]
. Setting append
to false
disables the appending.
Starting from version 5.84.0, webpack allows the append
option to be a function that accepts path data and an asset info object as arguments, and returns a string.
(pathData: PathData, assetInfo?: AssetInfo) => string;
moduleFilenameTemplate
(string
): See output.devtoolModuleFilenameTemplate
.
fallbackModuleFilenameTemplate
(string
): See link above.
namespace
(string
): See output.devtoolNamespace
.
module = true
(boolean
): Indicates whether loaders should generate source maps.
columns = true
(boolean
): Indicates whether column mappings should be used.
noSources = false
(boolean
): Prevents the source file content from being included in the source map.
publicPath
(string
): Emits absolute URLs with public path prefix, e.g. https://example.com/project/
.
fileContext
(string
): Makes the [file]
argument relative to this directory.
sourceRoot
(string
): Provide a custom value for the sourceRoot
property in the SourceMap.
The fileContext
option is useful when you want to store source maps in an upper level directory to avoid ../../
appearing in the absolute [url]
.
The following examples demonstrate some common use cases for this plugin.
You can use the following code to replace the configuration option devtool: inline-source-map
with an equivalent custom plugin configuration:
module.exports = {
// ...
devtool: false,
plugins: [new webpack.SourceMapDevToolPlugin({})],
};
The following code would exclude source maps for any modules in the vendor.js
bundle:
new webpack.SourceMapDevToolPlugin({
filename: '[file].map[query]',
exclude: ['vendor.js'],
});
Set a URL for source maps. Useful for hosting them on a host that requires authorization.
new webpack.SourceMapDevToolPlugin({
append: '\n//# sourceMappingURL=https://example.com/sourcemap/[url]',
filename: '[file].map[query]',
});
And for cases when source maps are stored in the upper level directory:
project
|- dist
|- public
|- bundle-[hash].js
|- sourcemaps
|- bundle-[hash].js.map
With the following config:
new webpack.SourceMapDevToolPlugin({
filename: 'sourcemaps/[file].map',
publicPath: 'https://example.com/project/',
fileContext: 'public',
});
Will produce the following URL:
https://example.com/project/sourcemaps/bundle-[hash].js.map
Originally, chunks (and modules imported inside them) were connected by a parent-child relationship in the internal webpack graph. The CommonsChunkPlugin
was used to avoid duplicated dependencies across them, but further optimizations were not possible.
Since webpack v4, the CommonsChunkPlugin
was removed in favor of optimization.splitChunks
.
Out of the box SplitChunksPlugin
should work well for most users.
By default it only affects on-demand chunks, because changing initial chunks would affect the script tags the HTML file should include to run the project.
Webpack will automatically split chunks based on these conditions:
node_modules
folderWhen trying to fulfill the last two conditions, bigger chunks are preferred.
Webpack provides a set of options for developers that want more control over this functionality.
This configuration object represents the default behavior of the SplitChunksPlugin
.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',
minSize: 20000,
minRemainingSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
string = '~'
By default webpack will generate names using origin and name of the chunk (e.g. vendors~main.js
). This option lets you specify the delimiter to use for the generated names.
string = 'async'
function (chunk)
RegExp
This indicates which chunks will be selected for optimization. When a string is provided, valid values are all
, async
, and initial
. Providing all
can be particularly powerful, because it means that chunks can be shared even between async and non-async chunks.
Note that it is applied to the fallback cache group as well (splitChunks.fallbackCacheGroup.chunks
).
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
// include all types of chunks
chunks: 'all',
},
},
};
Alternatively, you may provide a function for more control. The return value will indicate whether to include each chunk.
module.exports = {
//...
optimization: {
splitChunks: {
chunks(chunk) {
// exclude `my-excluded-chunk`
return chunk.name !== 'my-excluded-chunk';
},
},
},
};
If you are using webpack version 5.86.0 or later, you can also pass a regular expression:
module.exports = {
//...
optimization: {
splitChunks: {
chunks: /foo/,
},
},
};
number = 30
Maximum number of parallel requests when on-demand loading.
number = 30
Maximum number of parallel requests at an entry point.
[string] = ['javascript', 'unknown']
Sets the size types which are used when a number is used for sizes.
number = 1
The minimum times must a module be shared among chunks before splitting.
boolean
Prevents exposing path info when creating names for parts splitted by maxSize.
number = 20000
{ [index: string]: number }
Minimum size, in bytes, for a chunk to be generated.
number
{ [index: string]: number }
Minimum size reduction to the main chunk (bundle), in bytes, needed for a chunk to be generated. Meaning if splitting into a chunk does not reduce the size of the main chunk (bundle) by the given amount of bytes, it won't be split, even if it meets the splitChunks.minSize
value.
splitChunks.cacheGroups.{cacheGroup}.enforceSizeThreshold
number = 50000
Size threshold at which splitting is enforced and other restrictions (minRemainingSize, maxAsyncRequests, maxInitialRequests) are ignored.
splitChunks.cacheGroups.{cacheGroup}.minRemainingSize
number = 0
splitChunks.minRemainingSize
option was introduced in webpack 5 to avoid zero sized modules by ensuring that the minimum size of the chunk which remains after splitting is above a limit. Defaults to 0
in 'development' mode. For other cases splitChunks.minRemainingSize
defaults to the value of splitChunks.minSize
so it doesn't need to be specified manually except for the rare cases where deep control is required.
splitChunks.cacheGroups.{cacheGroup}.layer
RegExp
string
function
Assign modules to a cache group by module layer.
number = 0
Using maxSize
(either globally optimization.splitChunks.maxSize
per cache group optimization.splitChunks.cacheGroups[x].maxSize
or for the fallback cache group optimization.splitChunks.fallbackCacheGroup.maxSize
) tells webpack to try to split chunks bigger than maxSize
bytes into smaller parts. Parts will be at least minSize
(next to maxSize
) in size.
The algorithm is deterministic and changes to the modules will only have local effects. So that it is usable when using long term caching and doesn't require records. maxSize
is only a hint and could be violated when modules are bigger than maxSize
or splitting would violate minSize
.
When the chunk has a name already, each part will get a new name derived from that name. Depending on the value of optimization.splitChunks.hidePathInfo
it will add a key derived from the first module name or a hash of it.
maxSize
option is intended to be used with HTTP/2 and long term caching. It increases the request count for better caching. It could also be used to decrease the file size for faster rebuilding.
number
Like maxSize
, maxAsyncSize
can be applied globally (splitChunks.maxAsyncSize
), to cacheGroups (splitChunks.cacheGroups.{cacheGroup}.maxAsyncSize
), or to the fallback cache group (splitChunks.fallbackCacheGroup.maxAsyncSize
).
The difference between maxAsyncSize
and maxSize
is that maxAsyncSize
will only affect on-demand loading chunks.
number
Like maxSize
, maxInitialSize
can be applied globally (splitChunks.maxInitialSize
), to cacheGroups (splitChunks.cacheGroups.{cacheGroup}.maxInitialSize
), or to the fallback cache group (splitChunks.fallbackCacheGroup.maxInitialSize
).
The difference between maxInitialSize
and maxSize
is that maxInitialSize
will only affect initial load chunks.
boolean = false
function (module, chunks, cacheGroupKey) => string
string
Also available for each cacheGroup: splitChunks.cacheGroups.{cacheGroup}.name
.
The name of the split chunk. Providing false
will keep the same name of the chunks so it doesn't change names unnecessarily. It is the recommended value for production builds.
Providing a string or a function allows you to use a custom name. Specifying either a string or a function that always returns the same string will merge all common modules and vendors into a single chunk. This might lead to bigger initial downloads and slow down page loads.
If you choose to specify a function, you may find the chunk.name
property (where chunk
is an element of the chunks
array) particularly useful in choosing a name for your chunk.
If the splitChunks.name
matches an entry point name, the entry-point chunk & the cache group will be combined into a single chunk.
main.js
import _ from 'lodash';
console.log(_.join(['Hello', 'webpack'], ' '));
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
// cacheGroupKey here is `commons` as the key of the cacheGroup
name(module, chunks, cacheGroupKey) {
const moduleFileName = module
.identifier()
.split('/')
.reduceRight((item) => item);
const allChunksNames = chunks.map((item) => item.name).join('~');
return `${cacheGroupKey}-${allChunksNames}-${moduleFileName}`;
},
chunks: 'all',
},
},
},
},
};
Running webpack with following splitChunks
configuration would also output a chunk of the group common with next name: commons-main-lodash.js.e7519d2bb8777058fa27.js
(hash given as an example of real world output).
splitChunks.cacheGroups{cacheGroup}.usedExports
boolean = true
Figure out which exports are used by modules to mangle export names, omit unused exports and generate more efficient code.
When it is true
: analyse used exports for each runtime, when it is "global"
: analyse exports globally for all runtimes combined).
Cache groups can inherit and/or override any options from splitChunks.*
; but test
, priority
and reuseExistingChunk
can only be configured on cache group level. To disable any of the default cache groups, set them to false
.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
default: false,
},
},
},
};
splitChunks.cacheGroups.{cacheGroup}.priority
number = -20
A module can belong to multiple cache groups. The optimization will prefer the cache group with a higher priority
. The default groups have a negative priority to allow custom groups to take higher priority (default value is 0
for custom groups).
splitChunks.cacheGroups.{cacheGroup}.reuseExistingChunk
boolean = true
If the current chunk contains modules already split out from the main bundle, it will be reused instead of a new one being generated. This can affect the resulting file name of the chunk.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
reuseExistingChunk: true,
},
},
},
},
};
splitChunks.cacheGroups.{cacheGroup}.type
function
RegExp
string
Allows to assign modules to a cache group by module type.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
json: {
type: 'json',
},
},
},
},
};
splitChunks.cacheGroups.{cacheGroup}.test
function (module, { chunkGraph, moduleGraph }) => boolean
RegExp
string
Controls which modules are selected by this cache group. Omitting it selects all modules. It can match the absolute module resource path or chunk names. When a chunk name is matched, all modules in the chunk are selected.
Providing a function to{cacheGroup}.test
:
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
svgGroup: {
test(module) {
// `module.resource` contains the absolute path of the file on disk.
// Note the usage of `path.sep` instead of / or \, for cross-platform compatibility.
const path = require('path');
return (
module.resource &&
module.resource.endsWith('.svg') &&
module.resource.includes(`${path.sep}cacheable_svgs${path.sep}`)
);
},
},
byModuleTypeGroup: {
test(module) {
return module.type === 'javascript/auto';
},
},
},
},
},
};
In order to see what information is available in module
and chunks
objects, you can put debugger;
statement in the callback. Then run your webpack build in debug mode to inspect the parameters in Chromium DevTools.
Providing a RegExp
to {cacheGroup}.test
:
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
// Note the usage of `[\\/]` as a path separator for cross-platform compatibility.
test: /[\\/]node_modules[\\/]|vendor[\\/]analytics_provider|vendor[\\/]other_lib/,
},
},
},
},
};
splitChunks.cacheGroups.{cacheGroup}.filename
string
function (pathData, assetInfo) => string
Allows to override the filename when and only when it's an initial chunk.
All placeholders available in output.filename
are also available here.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
filename: '[name].bundle.js',
},
},
},
},
};
And as a function:
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
filename: (pathData) => {
// Use pathData object for generating filename string based on your requirements
return `${pathData.chunk.name}-bundle.js`;
},
},
},
},
},
};
It is possible to create a folder structure by providing path prefixing the filename: 'js/vendor/bundle.js'
.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
filename: 'js/[name]/bundle.js',
},
},
},
},
};
splitChunks.cacheGroups.{cacheGroup}.enforce
boolean = false
Tells webpack to ignore splitChunks.minSize
, splitChunks.minChunks
, splitChunks.maxAsyncRequests
and splitChunks.maxInitialRequests
options and always create chunks for this cache group.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
enforce: true,
},
},
},
},
};
splitChunks.cacheGroups.{cacheGroup}.idHint
string
Sets the hint for chunk id. It will be added to chunk's filename.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
defaultVendors: {
idHint: 'vendors',
},
},
},
},
};
// index.js
import('./a'); // dynamic import
// a.js
import 'react';
//...
Result: A separate chunk would be created containing react
. At the import call this chunk is loaded in parallel to the original chunk containing ./a
.
Why:
node_modules
react
is bigger than 30kbWhat's the reasoning behind this? react
probably won't change as often as your application code. By moving it into a separate chunk this chunk can be cached separately from your app code (assuming you are using chunkhash, records, Cache-Control or other long term cache approach).
// entry.js
// dynamic imports
import('./a');
import('./b');
// a.js
import './helpers'; // helpers is 40kb in size
//...
// b.js
import './helpers';
import './more-helpers'; // more-helpers is also 40kb in size
//...
Result: A separate chunk would be created containing ./helpers
and all dependencies of it. At the import calls this chunk is loaded in parallel to the original chunks.
Why:
helpers
is bigger than 30kbPutting the content of helpers
into each chunk will result into its code being downloaded twice. By using a separate chunk this will only happen once. We pay the cost of an additional request, which could be considered a tradeoff. That's why there is a minimum size of 30kb.
Create a commons
chunk, which includes all code shared between entry points.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: 'commons',
chunks: 'initial',
minChunks: 2,
},
},
},
},
};
Create a vendors
chunk, which includes all code from node_modules
in the whole application.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
};
Create a custom vendor
chunk, which contains certain node_modules
packages matched by RegExp
.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: 'vendor',
chunks: 'all',
},
},
},
},
};
This version of stylelint-webpack-plugin only works with webpack 5. For the webpack 4, see the 2.x branch.
This plugin uses stylelint
that helps you avoid errors and enforce conventions in your styles.
To begin, you'll need to install stylelint-webpack-plugin
:
npm install stylelint-webpack-plugin --save-dev
or
yarn add -D stylelint-webpack-plugin
or
pnpm add -D stylelint-webpack-plugin
[!NOTE]
You also need to install
stylelint >= 13
from npm, if you haven't already:
npm install stylelint --save-dev
or
yarn add -D stylelint
or
pnpm add -D stylelint
[!NOTE]
If you are using Stylelint 13 rather than 14+, you might also need to install
@types/stylelint
as a dev dependency if getting stylelint related type errors.
Then add the plugin to your webpack config. For example:
const StylelintPlugin = require('stylelint-webpack-plugin');
module.exports = {
// ...
plugins: [new StylelintPlugin(options)],
// ...
};
See stylelint's options for the complete list of options available. These options are passed through to the stylelint
directly.
cache
type cache = boolean;
true
The cache is enabled by default to decrease execution time.
cacheLocation
type cacheLocation = string;
node_modules/.cache/stylelint-webpack-plugin/.stylelintcache
Specify the path to the cache location. Can be a file or a directory.
configFile
type context = string;
undefined
Specify the config file location to be used by stylelint
.
Note:
By default this is handled by
stylelint
.
context
type context = string;
compiler.context
A string indicating the root of your files.
exclude
type exclude = string | Array<string>;
['node_modules', compiler.options.output.path]
Specify the files and/or directories to exclude. Must be relative to options.context
.
extensions
type extensions = string | Array<string>;
['css', 'scss', 'sass']
Specify extensions that should be checked.
files
type files = string | Array<string>;
null
Specify directories, files, or globs. Must be relative to options.context
. Directories are traversed recursively looking for files matching options.extensions
. File and glob patterns ignore options.extensions
.
fix
type fix = boolean;
false
If true
, stylelint
will fix as many errors as possible. The fixes are made to the actual source files. All unfixed errors will be reported. See Autofixing errors docs.
formatter
type formatter = string | (
results: Array<import('stylelint').LintResult>
) => string
'string'
Specify the formatter that you would like to use to format your results. See formatter option.
lintDirtyModulesOnly
type lintDirtyModulesOnly = boolean;
false
Lint only changed files, skip lint on start.
stylelintPath
type stylelintPath = string;
stylelint
Path to stylelint
instance that will be used for linting.
threads
type threads = boolean | number;
false
Set to true for an auto-selected pool size based on number of cpus. Set to a number greater than 1 to set an explicit pool size. Set to false, 1, or less to disable and only run in main process.
By default the plugin will auto adjust error reporting depending on stylelint errors/warnings counts.
You can still force this behavior by using emitError
or emitWarning
options:
emitError
type emitError = boolean;
true
The errors found will always be emitted, to disable set to false
.
emitWarning
type emitWarning = boolean;
true
The warnings found will always be emitted, to disable set to false
.
failOnError
type failOnError = boolean;
true
Will cause the module build to fail if there are any errors, to disable set to false
.
failOnWarning
type failOnWarning = boolean;
false
Will cause the module build to fail if there are any warnings, if set to true
.
quiet
type quiet = boolean;
false
Will process and report errors only and ignore warnings, if set to true
.
outputReport
type outputReport =
| boolean
| {
filePath?: string | undefined;
formatter?:
| (
| string
| ((results: Array<import('stylelint').LintResult>) => string)
)
| undefined;
};
false
Write the output of the errors to a file, for example a json
file for use for reporting.
The filePath
is relative to the webpack config: output.path
.
You can pass in a different formatter for the output file, if none is passed in the default/configured formatter will be used.
{
filePath: 'path/to/file';
formatter: 'json';
}
The svg-chunk-webpack-plugin
creates optimized SVG sprites, according to Webpack's entrypoints. Each sprite contains only the SVG dependencies listed on its entrypoints to improved code splitting, even on SVG files.
The plugin includes the popular SVGO package to generates clean and optimized SVG sprites.
Code splitting is the key to deliver files without any content that is unused by the pages. It already exists for CSS, Javascript and now for SVG files with this plugin.
On multiple page application, each pages must includes only its necessary dependencies. In other words, it must include only the SVG files imported by its entrypoint and all its dependencies.
With reusable components, SVGs are often duplicated on all the project. Now, you can create a global SVG library and every Javascript files can easily import any SVG from this library. Entrypoint dependencies are automatically updated, thanks to the Webpack compilation.
When you work with SVGs exported by design softwares, like Sketch or Illustrator, their source code is never optimized and often contains comments, CSS classes which can create conflicts between them. The plugin automatically cleans all SVGs before creating the sprite.
The plugin works without configuration with already the optimized settings. For advanced usage, see the section using configuration.
The plugin is available as a package with the name of svg-chunk-webpack-plugin
on npm and Github.
npm install svg-chunk-webpack-plugin --save-dev
yarn add svg-chunk-webpack-plugin --dev
Warning
svg-chunk-webpack-plugin@5
is ESM only.Note Minimum supported
Node.js
version is16.20.0
and Webpack>=5.10.3
.
The project includes a minimalist example in the ./example
directory. Run the npm run build:example
command to execute the Webpack example and see the plugin's implementation in action.
The plugin will generate one SVG sprite for each entrypoints. Sprites are built in the output path directory with all the other assets. Each sprite filename is composed with its entrypoint name (in the example below, that would be home.svg
).
First, let's add the loader and the plugin to the Webpack configuration.
Warning The loader and the plugin need to works together.
webpack.config.js
import SvgChunkWebpackPlugin from 'svg-chunk-webpack-plugin';
export default {
module: {
rules: [
{
test: /\.svg$/,
use: [
{
loader: SvgChunkWebpackPlugin.loader
}
]
}
]
},
plugins: [new SvgChunkWebpackPlugin()]
};
Note
For more flexibility and better performance, inline SVG files are better. Fewer HTTP requests, CSS properties to change the style, no flickering during the page load.
Then, include the sprite in the wanted pages (we use Twig in the following example).
home.html.twig
{{ include 'home.svg' }}
Finally, use the SVG with the <use>
tag, like the following example. Replace <svg_name>
by the SVG name (without the extension).
home.html.twig
<svg>
<use href="#<svg_name>"></use>
</svg>
The loader and the plugin accepts configuration to override the default behavior.
The loader configuration allow to personalize the SVGO configuration. SVGO optimization is executed during the loader process to optimize build performance.
configFile
Type:
type configFile = string | boolean;
Default: path.resolve(opts.root, 'svgo.config.js')
Tells the loader whether to load the custom SVGO configuration. Custom configuration can be disabled with configFile: false
.
webpack.config.js
export default {
module: {
rules: [
{
test: /\.svg$/,
loader: SvgChunkWebpackPlugin.loader,
options: {
configFile: './path/svgo.config.js'
}
}
]
}
};
SVGO have a default preset to optimize SVG files. See how to configure svgo for details.
svgo.config.js
export default {
multipass: true,
plugins: [
{
name: 'preset-default',
params: {
overrides: {
inlineStyles: {
onlyMatchedOnce: false
},
removeViewBox: false
}
}
},
{
name: 'convertStyleToAttrs'
}
]
};
The plugin configuration allow to personalize sprite settings.
filename
Type:
type filename = string;
Default: '[name].svg'
Tells the plugin whether to personalize the default sprite filename. The placeholder [name]
is automatically replaced by entrypoints names.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
filename: '[name].svg'
})
]
};
Note The
filename
parameter is compatible with Webpack caching placeholders, see the section caching.
svgstoreConfig
Type:
type svgstoreConfig = object;
Default: { cleanDefs: false, cleanSymbols: false, inline: true }
SVG sprites are built using the svgstore
package. Update the parameters according to your needs from the options list available on the svgstore documentation.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
svgstoreConfig: {
svgAttrs: {
'aria-hidden': true,
style: 'position: absolute; width: 0; height: 0; overflow: hidden;'
}
}
})
]
};
Note To avoid LinearGradient conflicts, avoid the
display: none
property which breaks SVG definitions.
generateSpritesManifest
Type:
type generateSpritesManifest = boolean;
Default: false
Tells the plugin whether to generate the sprites-manifest.json
. The JSON file contains the list of all SVG included by entrypoints.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
generateSpritesManifest: true
})
]
};
generateSpritesPreview
Type:
type generateSpritesPreview = boolean;
Default: false
Tells the plugin whether to generate the sprites-preview.html
. The HTML preview contains a display list of all SVG included by entrypoints with the SVG overviews and the names. See the sprites preview of the example.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
generateSpritesPreview: true
})
]
};
With webpack caching, several placeholders are available depending on your needs. With SVG inlined in the page, this option is not useful.
Note
The
[contenthash]
placeholder is the best option because it depends on the sprite content. Cache placeholders are expensive in build performance, use it only in production mode.
[contenthash]
The [contenthash]
placeholder will add a unique hash based on the content of the sprite. When the sprite's content changes, the hash will change as well.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
filename: '[name].[contenthash].svg'
})
]
};
[fullhash]
The [fullhash]
placeholder will add a unique hash generated for every build. When the compilation build is updated, the hash will change as well.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
filename: '[name].[fullhash].svg'
})
]
};
svg-chunk-webpack-plugin
is licensed under the MIT License.
Created with ♥ by @yoriiis.
This plugin uses terser to minify/minimize your JavaScript.
Webpack v5 comes with the latest terser-webpack-plugin
out of the box. If you are using Webpack v5 or above and wish to customize the options, you will still need to install terser-webpack-plugin
. Using Webpack v4, you have to install terser-webpack-plugin
v4.
To begin, you'll need to install terser-webpack-plugin
:
npm install terser-webpack-plugin --save-dev
or
yarn add -D terser-webpack-plugin
or
pnpm add -D terser-webpack-plugin
Then add the plugin to your webpack
config. For example:
webpack.config.js
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
},
};
And run webpack
via your preferred method.
Works only with source-map
, inline-source-map
, hidden-source-map
and nosources-source-map
values for the devtool
option.
Why?
eval
wraps modules in eval("string")
and the minimizer does not handle strings.cheap
has not column information and minimizer generate only a single line, which leave only a single mapping.Using supported devtool
values enable source map generation.
test
Type:
type test = string | RegExp | Array<string | RegExp>;
Default: /\.m?js(\?.*)?$/i
Test to match files against.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
test: /\.js(\?.*)?$/i,
}),
],
},
};
include
Type:
type include = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to include.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
include: /\/includes/,
}),
],
},
};
exclude
Type:
type exclude = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to exclude.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
exclude: /\/excludes/,
}),
],
},
};
parallel
Type:
type parallel = boolean | number;
Default: true
Use multi-process parallel running to improve the build speed.
Default number of concurrent runs: os.cpus().length - 1
.
Note
Parallelization can speedup your build significantly and is therefore highly recommended.
Warning
If you use Circle CI or any other environment that doesn't provide real available count of CPUs then you need to setup explicitly number of CPUs to avoid
Error: Call retries were exceeded
(see #143, #202).
boolean
Enable/disable multi-process parallel running.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
}),
],
},
};
number
Enable multi-process parallel running and set number of concurrent runs.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: 4,
}),
],
},
};
minify
Type:
type minify = (
input: {
[file: string]: string;
},
sourceMap: import("@jridgewell/trace-mapping").SourceMapInput | undefined,
minifyOptions: {
module?: boolean | undefined;
ecma?: import("terser").ECMA | undefined;
},
extractComments:
| boolean
| "all"
| "some"
| RegExp
| ((
astNode: any,
comment: {
value: string;
type: "comment1" | "comment2" | "comment3" | "comment4";
pos: number;
line: number;
col: number;
}
) => boolean)
| {
condition?:
| boolean
| "all"
| "some"
| RegExp
| ((
astNode: any,
comment: {
value: string;
type: "comment1" | "comment2" | "comment3" | "comment4";
pos: number;
line: number;
col: number;
}
) => boolean)
| undefined;
filename?: string | ((fileData: any) => string) | undefined;
banner?:
| string
| boolean
| ((commentsFile: string) => string)
| undefined;
}
| undefined
) => Promise<{
code: string;
map?: import("@jridgewell/trace-mapping").SourceMapInput | undefined;
errors?: (string | Error)[] | undefined;
warnings?: (string | Error)[] | undefined;
extractedComments?: string[] | undefined;
}>;
Default: TerserPlugin.terserMinify
Allows you to override default minify function. By default plugin uses terser package. Useful for using and testing unpublished versions or forks.
Warning
Always use
require
insideminify
function whenparallel
option enabled.
webpack.config.js
// Can be async
const minify = (input, sourceMap, minimizerOptions, extractsComments) => {
// The `minimizerOptions` option contains option from the `terserOptions` option
// You can use `minimizerOptions.myCustomOption`
// Custom logic for extract comments
const { map, code } = require("uglify-module") // Or require('./path/to/uglify-module')
.minify(input, {
/* Your options for minification */
});
return { map, code, warnings: [], errors: [], extractedComments: [] };
};
// Used to regenerate `fullhash`/`chunkhash` between different implementation
// Example: you fix a bug in custom minimizer/custom function, but unfortunately webpack doesn't know about it, so you will get the same fullhash/chunkhash
// to avoid this you can provide version of your custom minimizer
// You don't need if you use only `contenthash`
minify.getMinimizerVersion = () => {
let packageJson;
try {
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
packageJson = require("uglify-module/package.json");
} catch (error) {
// Ignore
}
return packageJson && packageJson.version;
};
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
myCustomOption: true,
},
minify,
}),
],
},
};
terserOptions
Type:
type terserOptions = {
compress?: boolean | CompressOptions;
ecma?: ECMA;
enclose?: boolean | string;
ie8?: boolean;
keep_classnames?: boolean | RegExp;
keep_fnames?: boolean | RegExp;
mangle?: boolean | MangleOptions;
module?: boolean;
nameCache?: object;
format?: FormatOptions;
/** @deprecated */
output?: FormatOptions;
parse?: ParseOptions;
safari10?: boolean;
sourceMap?: boolean | SourceMapOptions;
toplevel?: boolean;
};
Default: default
Terser options.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
ecma: undefined,
parse: {},
compress: {},
mangle: true, // Note `mangle.properties` is `false` by default.
module: false,
// Deprecated
output: null,
format: null,
toplevel: false,
nameCache: null,
ie8: false,
keep_classnames: undefined,
keep_fnames: false,
safari10: false,
},
}),
],
},
};
extractComments
Type:
type extractComments =
| boolean
| string
| RegExp
| ((
astNode: any,
comment: {
value: string;
type: "comment1" | "comment2" | "comment3" | "comment4";
pos: number;
line: number;
col: number;
}
) => boolean)
| {
condition?:
| boolean
| "all"
| "some"
| RegExp
| ((
astNode: any,
comment: {
value: string;
type: "comment1" | "comment2" | "comment3" | "comment4";
pos: number;
line: number;
col: number;
}
) => boolean)
| undefined;
filename?: string | ((fileData: any) => string) | undefined;
banner?:
| string
| boolean
| ((commentsFile: string) => string)
| undefined;
};
Default: true
Whether comments shall be extracted to a separate file, (see details).
By default extract only comments using /^\**!|@preserve|@license|@cc_on/i
regexp condition and remove remaining comments.
If the original file is named foo.js
, then the comments will be stored to foo.js.LICENSE.txt
.
The terserOptions.format.comments
option specifies whether the comment will be preserved, i.e. it is possible to preserve some comments (e.g. annotations) while extracting others or even preserving comments that have been extracted.
boolean
Enable/disable extracting comments.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: true,
}),
],
},
};
string
Extract all
or some
(use /^\**!|@preserve|@license|@cc_on/i
RegExp) comments.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: "all",
}),
],
},
};
RegExp
All comments that match the given expression will be extracted to the separate file.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: /@extract/i,
}),
],
},
};
function
All comments that match the given expression will be extracted to the separate file.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: (astNode, comment) => {
if (/@extract/i.test(comment.value)) {
return true;
}
return false;
},
}),
],
},
};
object
Allow to customize condition for extract comments, specify extracted file name and banner.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: {
condition: /^\**!|@preserve|@license|@cc_on/i,
filename: (fileData) => {
// The "fileData" argument contains object with "filename", "basename", "query" and "hash"
return `${fileData.filename}.LICENSE.txt${fileData.query}`;
},
banner: (licenseFile) => {
return `License information can be found in ${licenseFile}`;
},
},
}),
],
},
};
condition
Type:
type condition =
| boolean
| "all"
| "some"
| RegExp
| ((
astNode: any,
comment: {
value: string;
type: "comment1" | "comment2" | "comment3" | "comment4";
pos: number;
line: number;
col: number;
}
) => boolean)
| undefined;
Condition what comments you need extract.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: {
condition: "some",
filename: (fileData) => {
// The "fileData" argument contains object with "filename", "basename", "query" and "hash"
return `${fileData.filename}.LICENSE.txt${fileData.query}`;
},
banner: (licenseFile) => {
return `License information can be found in ${licenseFile}`;
},
},
}),
],
},
};
filename
Type:
type filename = string | ((fileData: any) => string) | undefined;
Default: [file].LICENSE.txt[query]
Available placeholders: [file]
, [query]
and [filebase]
([base]
for webpack 5).
The file where the extracted comments will be stored.
Default is to append the suffix .LICENSE.txt
to the original filename.
Warning
We highly recommend using the
txt
extension. Usingjs
/cjs
/mjs
extensions may conflict with existing assets which leads to broken code.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: {
condition: /^\**!|@preserve|@license|@cc_on/i,
filename: "extracted-comments.js",
banner: (licenseFile) => {
return `License information can be found in ${licenseFile}`;
},
},
}),
],
},
};
banner
Type:
type banner = string | boolean | ((commentsFile: string) => string) | undefined;
Default: /*! For license information please see ${commentsFile} */
The banner text that points to the extracted file and will be added on top of the original file.
Can be false
(no banner), a String
, or a Function<(string) -> String>
that will be called with the filename where extracted comments have been stored.
Will be wrapped into comment.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: {
condition: true,
filename: (fileData) => {
// The "fileData" argument contains object with "filename", "basename", "query" and "hash"
return `${fileData.filename}.LICENSE.txt${fileData.query}`;
},
banner: (commentsFile) => {
return `My custom banner about license information ${commentsFile}`;
},
},
}),
],
},
};
Extract all legal comments (i.e. /^\**!|@preserve|@license|@cc_on/i
) and preserve /@license/i
comments.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
format: {
comments: /@license/i,
},
},
extractComments: true,
}),
],
},
};
If you avoid building with comments, use this config:
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
format: {
comments: false,
},
},
extractComments: false,
}),
],
},
};
uglify-js
UglifyJS
is a JavaScript parser, minifier, compressor and beautifier toolkit.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
minify: TerserPlugin.uglifyJsMinify,
// `terserOptions` options will be passed to `uglify-js`
// Link to options - https://github.com/mishoo/UglifyJS#minify-options
terserOptions: {},
}),
],
},
};
swc
swc
is a super-fast compiler written in rust; producing widely-supported javascript from modern standards and typescript.
Warning
the
extractComments
option is not supported and all comments will be removed by default, it will be fixed in future
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
minify: TerserPlugin.swcMinify,
// `terserOptions` options will be passed to `swc` (`@swc/core`)
// Link to options - https://swc.rs/docs/config-js-minify
terserOptions: {},
}),
],
},
};
esbuild
esbuild
is an extremely fast JavaScript bundler and minifier.
Warning
the
extractComments
option is not supported and all legal comments (i.e. copyright, licenses and etc) will be preserved
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
minify: TerserPlugin.esbuildMinify,
// `terserOptions` options will be passed to `esbuild`
// Link to options - https://esbuild.github.io/api/#minify
// Note: the `minify` options is true by default (and override other `minify*` options), so if you want to disable the `minifyIdentifiers` option (or other `minify*` options) please use:
// terserOptions: {
// minify: false,
// minifyWhitespace: true,
// minifyIdentifiers: false,
// minifySyntax: true,
// },
terserOptions: {},
}),
],
},
};
Override default minify function - use uglify-js
for minification.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
minify: (file, sourceMap) => {
// https://github.com/mishoo/UglifyJS2#minify-options
const uglifyJsOptions = {
/* your `uglify-js` package options */
};
if (sourceMap) {
uglifyJsOptions.sourceMap = {
content: sourceMap,
};
}
return require("uglify-js").minify(file, uglifyJsOptions);
},
}),
],
},
};
With default terser minify function:
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: true,
},
}),
],
},
};
With built-in minify functions:
import type { JsMinifyOptions as SwcOptions } from "@swc/core";
import type { MinifyOptions as UglifyJSOptions } from "uglify-js";
import type { TransformOptions as EsbuildOptions } from "esbuild";
import type { MinifyOptions as TerserOptions } from "terser";
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin<SwcOptions>({
minify: TerserPlugin.swcMinify,
terserOptions: {
// `swc` options
},
}),
new TerserPlugin<UglifyJSOptions>({
minify: TerserPlugin.uglifyJsMinify,
terserOptions: {
// `uglif-js` options
},
}),
new TerserPlugin<EsbuildOptions>({
minify: TerserPlugin.esbuildMinify,
terserOptions: {
// `esbuild` options
},
}),
// Alternative usage:
new TerserPlugin<TerserOptions>({
minify: TerserPlugin.terserMinify,
terserOptions: {
// `terser` options
},
}),
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
Ignore the specified files, i.e. those matching the provided paths or regular expressions, while in watch mode.
new webpack.WatchIgnorePlugin({ paths });
paths
(Array<string | RegExp>
): A list of RegExps or absolute paths to directories or files that should be ignored.