Printable

AutomaticPrefetchPlugin

AutomaticPrefetchPlugin 会观察之前编译的 所有模块 的变化,以改进增量构建的时间。对比PrefetchPlugin 而言,PrefetchPlugin 是预先发现 单个模块

webpack.config.js

module.exports = {
  // ...
  plugins: [new webpack.AutomaticPrefetchPlugin()],
};

BannerPlugin

为每个 chunk 文件头部添加 banner。

const webpack = require('webpack');

new webpack.BannerPlugin(banner);
// 或者
new webpack.BannerPlugin(options);

选项

{
  banner: string | function, // 其值为字符串或函数,将作为注释存在
  raw: boolean, // 如果值为 true,将直接输出,不会被作为注释
  entryOnly: boolean, // 如果值为 true,将只在入口 chunks 文件中添加
  test: string | RegExp | [string, RegExp], // 包含所有匹配的模块
  include: string | RegExp | [string, RegExp], // 根据条件匹配所有模块
  exclude: string | RegExp | [string, RegExp], // 根据条件排除所有模块
  footer?: boolean, // 如果值为 true,banner 将会位于编译结果的最下方
}

用法

import webpack from 'webpack';

// 字符串
new webpack.BannerPlugin({
  banner: 'hello world',
});

// 函数
new webpack.BannerPlugin({
  banner: (yourVariable) => {
    return `yourVariable: ${yourVariable}`;
  },
});

占位符

从 webpack 2.5.0 开始,会对 banner 字符串中的占位符取值:

import webpack from 'webpack';

new webpack.BannerPlugin({
  banner:
    'fullhash:[fullhash], chunkhash:[chunkhash], name:[name], filebase:[filebase], query:[query], file:[file]',
});

CommonsChunkPlugin

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);

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.
}

Examples

Commons chunk for entries

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>

Explicit vendor chunk

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>

Move common modules into the parent chunk

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)
});

Extra async commons chunk

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)
});

Passing the minChunks property a function

You 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');
  },
});

Manifest file

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,
});

Combining implicit common vendor chunks and manifest file

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,
  }),
];

More Examples

CompressionWebpackPlugin

npm node deps tests cover chat size

Prepare compressed versions of assets to serve them with Content-Encoding.

Getting Started

To begin, you'll need to install compression-webpack-plugin:

npm install compression-webpack-plugin --save-dev

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.

Options

NameTypeDefaultDescription
test{String|RegExp|Array<String|RegExp>}undefinedInclude all assets that pass test assertion
include{String|RegExp|Array<String|RegExp>}undefinedInclude all assets matching any of these conditions
exclude{String|RegExp|Array<String|RegExp>}undefinedExclude all assets matching any of these conditions
algorithm{String|Function}gzipThe compression algorithm/function
compressionOptions{Object}maximum available compression level, for gzip: { level: 9 }Compression options for algorithm
threshold{Number}0Only assets bigger than this size are processed (in bytes)
minRatio{Number}0.8Only assets that compress better than this ratio are processed (minRatio = Compressed Size / Original Size)
filename{String|Function}[path][base].gzThe target asset filename
deleteOriginalAssets{Boolean|'keep-source-map'}falseWhether to delete the original assets or not

test

Type: 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: 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: 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: String|Function Default: gzip

The compression algorithm/function.

ℹ️ If you use custom function for the algorithm option, the default value of the compressionOptions 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: Object Default: { level: 9 }

Compression options for algorithm.

You can find all options here zlib.

ℹ️ 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: 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: 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: String|Function 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: Boolean | 'keep-source-map' 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',
    }),
  ],
};

Examples

Using Zopfli

Prepare compressed versions of assets using zopfli library.

ℹ️ @gfx/zopfli require minimum 8 version of node.

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);
      },
    }),
  ],
};

Using Brotli

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.

Multiple compressed versions of assets for different algorithm

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,
    }),
  ],
};

Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.

CONTRIBUTING

License

MIT

ContextExclusionPlugin

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/)],
};

ContextReplacementPlugin

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:

Usage

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).

Content Callback

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
  });
});

Other Options

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',
});

CopyWebpackPlugin

npm node deps tests cover chat size

Copies individual files or entire directories, which already exist, to the build directory.

Getting Started

To begin, you'll need to install copy-webpack-plugin:

npm install copy-webpack-plugin --save-dev

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' },
      ],
    }),
  ],
};

ℹ️ 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.

ℹ️ If you want webpack-dev-server to write files to the output directory during development, you can force it with the writeToDisk option or the write-file-webpack-plugin.

ℹ️ You can get the original source filename from Asset Objects.

Options

NameTypeDescription
patterns{Array<String|Object>}Specify file related patterns for plugin
options{Object}Specify options for plugin

The plugin's signature:

webpack.config.js

const CopyPlugin = require('copy-webpack-plugin');

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        { from: 'source', to: 'dest' },
        { from: 'other', to: 'public' },
      ],
      options: {
        concurrency: 100,
      },
    }),
  ],
};

Patterns

NameTypeDefaultDescription
from{String}undefinedGlob or path from where we copy files.
to{String|Function}compiler.options.outputOutput path.
context{String}options.context || compiler.options.contextA path that determines how to interpret the from path.
globOptions{Object}undefinedOptions passed to the glob pattern matching library including ignore option.
filter{Function}undefinedAllows to filter copied assets.
toType{String}undefinedDeterminate what is to option - directory, file or template.
force{Boolean}falseOverwrites files already in compilation.assets (usually added by other plugins/loaders).
priority{Number}0Allows you to specify the copy priority.
transform{Object}undefinedAllows to modify the file contents. Enable transform caching. You can use { transform: {cache: { key: 'my-cache-key' }} } to invalidate the cache.
transformAll{Function}undefinedAllows you to modify the contents of multiple files and save the result to one file.
noErrorOnMissing{Boolean}falseDoesn't generate an error on missing file(s).
info{Object|Function}undefinedAllows to add assets info.

from

Type: String Default: undefined

Glob or path from where we copy files. Globs accept fast-glob pattern-syntax. Glob can only be a string.

⚠️ Don't use directly \\ in from option if it is a glob (i.e path\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: String|Function Default: compiler.options.output

String

Output path.

⚠️ Don't use directly \\ in to (i.e path\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 / or path 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.

⚠️ Don't return directly \\ in to (i.e path\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 / or path 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: String Default: options.context|compiler.options.context

A path that determines how to interpret the from path.

⚠️ Don't use directly \\ in context (i.e path\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 / or path methods.

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: 'src/*.txt',
          to: 'dest/',
          context: 'app/',
        },
      ],
    }),
  ],
};

The context option can be an absolute or relative path. If context is a relative, then it is converted to absolute based to compiler.options.context

Also, context indicates how to interpret the search results. Further, he is considered in this role.

To determine the structure from which the found resources will be copied to the destination folder, the context option is used.

If from is a file, then context is equal to the directory in which this file is located. Accordingly, the result will be only the file name.

If from is a directory, then context is the same as from and is equal to the directory itself. In this case, the result will be a hierarchical structure of the found folders and files relative to the specified directory.

If from is a glob, then regardless of the context option, the result will be the structure specified in the from option

More examples

globOptions

Type: Object 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: Function Default: undefined

ℹ️ 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: String 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.

NameTypeDefaultDescription
'dir'{String}undefinedIf to has no extension or ends on '/'
'file'{String}undefinedIf to is not a directory and is not a template
'template'{String}undefinedIf 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: 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: 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: Function|Object 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
NameTypeDefaultDescription
transformer{Function}undefinedAllows to modify the file contents.
cache{Boolean|Object}falseEnable transform caching. You can use transform: { cache: { key: 'my-cache-key' } } to invalidate the cache.
transformer

Type: Function 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: Boolean|Object 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 cache directory and invalidation keys.

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: 'src/*.png',
          to: 'dest/',
          transform: {
            transformer(content, path) {
              return optimize(content);
            },
            cache: {
              directory: path.resolve(__dirname, 'cache-directory'),
              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: {
              directory: path.resolve(__dirname, 'cache-directory'),
              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: {
              directory: path.resolve(__dirname, 'cache-directory'),
              keys: async (defaultCacheKeys, absoluteFrom) => {
                const keys = await getCustomCacheInvalidationKeysAsync();

                return {
                  ...defaultCacheKeys,
                  keys,
                };
              },
            },
          },
        },
      ],
    }),
  ],
};

transformAll

类型:Function 默认值:undefined

允许你去更改多个文件的内容,并将结果保存到一个文件中。

ℹ️ 必须指定 to 配置项为一个文件。只允许使用 [contenthash][fullhash] 模板字符串。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: 'src/**/*.txt',
          to: 'dest/file.txt',
          // `assets` 参数是一个符合 pattern.from ("src/**/*.txt") 静态资源数组。
          transformAll(assets) {
            const result = assets.reduce((accumulator, asset) => {
              // 静态资源内容可以使用 `source` 方法从 `asset.source` 中获取。
              // 静态资源内容是一个 [`Buffer`](https://nodejs.org/api/buffer.html) 对象,可以使用 `content.toString()` 将其转为 `String`
              const content = asset.data;

              accumulator = `${accumulator}${content}\n`;
              return accumulator;
            }, '');

            return result;
          },
        },
      ],
    }),
  ],
};

noErrorOnMissing

Type: 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: Object|Function<Object> 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 }),
        },
      ],
    }),
  ],
};

Options

NameTypeDefaultDescription
concurrency{Number}100Limits the number of simultaneous requests to fs

concurrency

limits the number of simultaneous requests to fs

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [...patterns],
      options: { concurrency: 50 },
    }),
  ],
};

Examples

Different variants 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;
From is a Glob

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 want only content src/directory-nested/, you should only indicate glob in from. The path to the folder in which the search should take place, should be moved to context.

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
From is a Dir

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
From is a File
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

Ignoring files

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/**',
            ],
          },
        },
      ],
    }),
  ],
};

Flatten copy

Removes all directory references and only copies file names.

⚠️ 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

Copy in new directory

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",

Skip running JavaScript files through a minimizer $#skiprunningjavaScriptfilesthroughaminimizer$

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

当时用 yarn workspaces 或者 monorepos 时,由于包提升方式不同,node_modules 的相对复制路径可能会失效。 为了避免这种情况,请使用 require.resolve 指定复制路径。

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: `${path.dirname(
            require.resolve(`${moduleName}/package.json`)
          )}/target`,
          to: 'target',
        },
      ],
    }),
  ],
};

Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.

CONTRIBUTING

License

MIT

CssMinimizerWebpackPlugin

npm node deps tests cover chat size

这个插件使用 cssnano 优化和压缩 CSS。

就像 optimize-css-assets-webpack-plugin 一样,但在 source maps 和 assets 中使用查询字符串会更加准确,支持缓存和并发模式下运行。

起步

首先,你需要安装 css-minimizer-webpack-plugin

npm install css-minimizer-webpack-plugin --save-dev

接着在 webpack 配置中加入该插件。示例:

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: [
      // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
      // `...`,
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [new MiniCssExtractPlugin()],
};

这将仅在生产环境开启 CSS 优化。

如果还想在开发环境下启用 CSS 优化,请将 optimization.minimize 设置为 true:

webpack.config.js

// [...]
module.exports = {
  optimization: {
    // [...]
    minimize: true,
  },
};

然后通过你喜欢的方式运行 webpack

关于 source maps 的提示

仅对 devtool 配置项的 source-mapinline-source-maphidden-source-mapnosources-source-map 值生效。

为什么呢?因为 CSS 仅支持这些 source map 类型。

插件支持 devtool 并且使用 SourceMapDevToolPlugin 插件。 使用受支持的 devtool 值可以启用 source map 生成。 使用 SourceMapDevToolPlugin 并启用 columns 配置项可以启用 source map 生成。

使用 source map 将错误信息位置映射到 modules 中(这降低了复杂度)。 如果你是用自定义 minify 函数,请阅读 minify 章节以确保正确处理 source map。

选项

选项名类型默认值描述
testString|RegExp|Array<String|RegExp>/\.css(\?.*)?$/i匹配要处理的文件
includeString|RegExp|Array<String|RegExp>undefined要引入的文件
excludeString|RegExp|Array<String|RegExp>undefined要排除的文件
parallelBoolean|Numbertrue启用/禁用多进程并行处理。
minifyFunction|Array<Function>CssMinimizerPlugin.cssnanoMinify允许覆盖默认的 minify 函数。
minimizerOptionsObject|Array<Object>{ preset: 'default' }Cssnano 优化 配置项
warningsFilterFunction<(warning, file, source) -> Boolean>() => true允许过滤掉 css-minimizer 的警告。

test

类型:String|RegExp|Array<String|RegExp> - 默认值:/\.css(\?.*)?$/i

用来匹配文件。

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        test: /\.foo\.css$/i,
      }),
    ],
  },
};

include

类型:String|RegExp|Array<String|RegExp> 默认值:undefined

要包含的文件。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        include: /\/includes/,
      }),
    ],
  },
};

exclude

类型:String|RegExp|Array<String|RegExp> 默认值:undefined

要排除的文件。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        exclude: /\/excludes/,
      }),
    ],
  },
};

parallel

类型:Boolean|Number 默认值:true

使用多进程并发执行,提升构建速度。 运行时默认的并发数:os.cpus().length - 1

ℹ️ 并行化可以显著提升构建速度,所以强烈建议使用。 如果启用了并行化,minimizerOptions 中的包必须通过字符串引入(packageName 或者 require.resolve(packageName))。在 minimizerOptions 获取更多详细信息。

Boolean

启用/禁用多进程并发执行。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        parallel: true,
      }),
    ],
  },
};

Number

启用多进程并发执行且设置并发数。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        parallel: 4,
      }),
    ],
  },
};

minify

类型:Function|Array<Function> 默认值:CssMinimizerPlugin.cssnanoMinify

允许覆盖默认的 minify 函数。 默认情况下,插件使用 cssnano 包。 对于使用和测试未发布或版本衍生版本很有用。

可选配置:

  • CssMinimizerPlugin.cssnanoMinify
  • CssMinimizerPlugin.cssoMinify
  • CssMinimizerPlugin.cleanCssMinify
  • CssMinimizerPlugin.esbuildMinify
  • async (data, inputMap, minimizerOptions) => {return {code: "a{color: red}", map: "...", warnings: [], errors: []}}

⚠️ 启用 parallel 选项时,始终在 minify 函数中使用 require

Function

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: {
          level: {
            1: {
              roundingPrecision: 'all=3,px=5',
            },
          },
        },
        minify: CssMinimizerPlugin.cleanCssMinify,
      }),
    ],
  },
};

Array

如果 minify 配置项传入一个数组,minimizerOptions 也必须是个数组。 miniify 数组中的函数索引对应于 minimizerOptions 数组中具有相同索引的 options 对象。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: [
          {}, // 第一个函数的配置项(CssMinimizerPlugin.cssnanoMinify)
          {}, // 第二个函数的配置项(CssMinimizerPlugin.cleanCssMinify)
          {}, // 第三个函数的配置项
        ],
        minify: [
          CssMinimizerPlugin.cssnanoMinify,
          CssMinimizerPlugin.cleanCssMinify,
          async (data, inputMap, minimizerOptions) => {
            // To do something
            return {
              code: `a{color: red}`,
              map: `{"version": "3", ...}`,
              warnings: [],
              errors: [],
            };
          },
        ],
      }),
    ],
  },
};

minimizerOptions

类型:Object|Array<Object> 默认值:{ preset: 'default' }

Cssnano 优化 选项.

Object

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: {
          preset: [
            'default',
            {
              discardComments: { removeAll: true },
            },
          ],
        },
      }),
    ],
  },
};

Array

miniify 数组中的函数索引对应于 minimizerOptions 数组中具有相同索引的 options 对象。 如果你使用了类似于 minimizerOptions 的对象,那么所有函数都会接受它。

如果启用了并行化,minimizerOptions 中的包必须通过字符串引入(packageName 或者 require.resolve(packageName))。在这种情况下,我们不应该使用 require/import

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: {
          preset: require.resolve('cssnano-preset-simple'),
        },
      }),
    ],
  },
};
processorOptions (⚠ only cssnano)

类型:Object 默认值:{ from: assetName }

允许配置 cssnano 的 processoptions 配置项。 parser stringifiersyntax 可以是一个函数,也可以是一个字符串,用来表示将会被导出的模块。

⚠️ 如果传入一个函数,则必须禁用parallel 配置项。.

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

类型:Function<(warning, file, source) -> Boolean> 默认值:() => true

允许过滤 css-minimizer warnings(默认使用 cssnano)。 返回 true 将保留 warning,否则返回假值(false/null/undefined)。

⚠️ 如果没有使用 source maps,source 参数将包含 undefined

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;
        },
      }),
    ],
  },
};

示例

使用 sourcemaps

不要忘记为所有 loader 启用 sourceMap 选项。

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  devtool: 'source-map',
  module: {
    loaders: [
      {
        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()],
};

移除所有注释

移除所有注释(包括以 /*! 开头的注释)。

module.exports = {
  optimization: {
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: {
          preset: [
            'default',
            {
              discardComments: { removeAll: true },
            },
          ],
        },
      }),
    ],
  },
};

使用自定义 minifier csso

webpack.config.js

module.exports = {
  devtool: 'source-map',
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minify: CssMinimizerPlugin.cssoMinify,
        // Uncomment this line for options
        // minimizerOptions: { restructure: false },
      }),
    ],
  },
};

使用自定义 minifier clean-css

webpack.config.js

module.exports = {
  devtool: 'source-map',
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minify: CssMinimizerPlugin.cleanCssMinify,
        // Uncomment this line for options
        // minimizerOptions: { compatibility: 'ie11,-properties.merging' },
      }),
    ],
  },
};

Using custom minifier esbuild

webpack.config.js

module.exports = {
  devtool: 'source-map',
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minify: CssMinimizerPlugin.esbuildMinify,
      }),
    ],
  },
};

贡献

如果你还没有阅读,请花一点时间阅读我们的贡献指南。

CONTRIBUTING

License

MIT

DefinePlugin

DefinePlugin 允许在 编译时 将你代码中的变量替换为其他值或表达式。这在需要根据开发模式与生产模式进行不同的操作时,非常有用。例如,如果想在开发构建中进行日志记录,而不在生产构建中进行,就可以定义一个全局常量去判断是否记录日志。这就是 DefinePlugin 的发光之处,设置好它,就可以忘掉开发环境和生产环境的构建规则。

new webpack.DefinePlugin({
  // 定义...
});

Usage

传递给 DefinePlugin 的每个键都是一个标识符或多个以 . 连接的标识符。

  • 如果该值为字符串,它将被作为代码片段来使用。
  • 如果该值不是字符串,则将被转换成字符串(包括函数方法)。
  • 如果值是一个对象,则它所有的键将使用相同方法定义。
  • 如果键添加 typeof 作为前缀,它会被定义为 typeof 调用。

这些值将内联到代码中,从而允许通过代码压缩来删除冗余的条件判断。

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');
}

未经 webpack 压缩过的代码:

if (!true) {
  console.log('Debug info');
}
if (true) {
  console.log('Production log');
}

经过压缩后:

console.log('Production log');

Feature Flags

使用 feature flags 在生产/开发构建中可以启用/禁用项目的不同特性。

new webpack.DefinePlugin({
  NICE_FEATURE: JSON.stringify(true),
  EXPERIMENTAL_FEATURE: JSON.stringify(false),
});

Service URL

在生产或开发构建中使用不同的服务 URL:

new webpack.DefinePlugin({
  SERVICE_URL: JSON.stringify('https://dev.example.com'),
});

Runtime values via 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.

DllPlugin

DllPluginDllReferencePlugin 用某种方法实现了拆分 bundles,同时还大幅度提升了构建的速度。"DLL" 一词代表微软最初引入的动态链接库。

DllPlugin

此插件用于在单独的 webpack 配置中创建一个 dll-only-bundle。 此插件会生成一个名为 manifest.json 的文件,这个文件是用于让 DllReferencePlugin 能够映射到相应的依赖上。

  • context(可选): manifest 文件中请求的 context (默认值为 webpack 的 context)
  • format (boolean = false):如果为 true,则 manifest json 文件 (输出文件) 将被格式化。
  • name:暴露出的 DLL 的函数名(TemplatePaths[fullhash] & [name]
  • path:manifest.json 文件的 绝对路径(输出文件)
  • entryOnly (boolean = true):如果为 true,则仅暴露入口
  • type:dll bundle 的类型
new webpack.DllPlugin(options);

在给定的 path 路径下创建一个 manifest.json 文件。这个文件包含了从 require 和 import 中 request 到模块 id 的映射。 DllReferencePlugin 也会用到这个文件。

此插件与 output.library 的选项相结合可以暴露出(也称为放入全局作用域)dll 函数。

DllReferencePlugin

此插件配置在 webpack 的主配置文件中,此插件会把 dll-only-bundles 引用到需要的预编译的依赖中。

  • context:(绝对路径) manifest (或者是内容属性)中请求的上下文
  • extensions:用于解析 dll bundle 中模块的扩展名 (仅在使用 'scope' 时使用)。
  • manifest :包含 contentname 的对象,或者是一个字符串 —— 编译时用于加载 JSON manifest 的绝对路径
  • content (可选): 请求到模块 id 的映射(默认值为 manifest.content
  • name (可选):dll 暴露地方的名称(默认值为 manifest.name)(可参考externals
  • scope (可选):dll 中内容的前缀
  • sourceType (可选):dll 是如何暴露的 (libraryTarget)
new webpack.DllReferencePlugin(options);

通过引用 dll 的 manifest 文件来把依赖的名称映射到模块的 id 上,之后再在需要的时候通过内置的 __webpack_require__ 函数来 require 对应的模块

模式(Modes)

这个插件支持两种模式,分别是作用域(scoped)和映射(mapped)。

Scoped Mode

dll 中的内容可以使用模块前缀的方式引用,举例来说,设置 scope = 'xyz',这个 dll 中的名为 abc 的文件可以通过 require('xyz/abc') 来获取。

Mapped Mode

dll 中的内容会被映射到当前目录下。如果被 require 的文件与 dll 中的某个文件匹配(解析之后),那么这个 dll 中的文件就会被使用。

由于这是在解析了 dll 中每个文件之后才触发的,因此相同的路径必须能够确保这个 dll bundle 的使用者(不一定是人,可指某些代码)有权限访问。 举例来说, 假如一个 dll bundle 中含有 loadash 库以及文件 abc, 那么 require("lodash")require("./abc") 都不会被编译进主 bundle 文件中,而是会被 dll 所使用。

用法(Usage)

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',
});

示例

VendorUser

两个单独的用例,用来分别演示作用域(scope)和上下文(context)。

参考

Source

Tests

EnvironmentPlugin

The EnvironmentPlugin is shorthand for using the DefinePlugin on process.env keys.

Usage

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),
});

Usage with default values

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');
}

Use Case: Git Version

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'),
});

DotenvPlugin

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)
});

EslintWebpackPlugin

npm node deps tests coverage chat size

eslint-webpack-plugin 3.0 仅支持 webpack 5。对于 webpack 4 请查看 2.x 分支

该插件使用 eslint 来查找和修复 JavaScript 代码中的问题。

开始

首先,需要安装 eslint-webpack-plugin

npm install eslint-webpack-plugin --save-dev

注意: 如果未安装 eslint >= 7 ,你还需先通过 npm 安装:

npm install eslint --save-dev

然后把插件添加到你的 webpack 配置。例如:

const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
  // ...
  plugins: [new ESLintPlugin(options)],
  // ...
};

选项

你可以传入 eslint 参数

注意你提供的配置选项会传给 ESLint 类。 这是一组和你在 package.json.eslintrc 所指定选项不同的选项。 查阅 eslint 文档 获取更多详情。

警告: 在 eslint-webpack-plugin 1.x 版本中,配置项会传递给已废弃的 CLIEngine

context

  • 类型:String
  • 默认值:compiler.context

指定文件根目录,类型为字符串。

eslintPath

  • 类型:String
  • 默认值:eslint

用于 linting 的 eslint 实例的路径。如果 eslintPath 是类似官方 eslint 的目录,或者指定了 formatter 选项,那么就不需要安装 eslint 了。

extensions

  • 类型:String|Array[String]
  • 默认值:'js'

指定需要检查的扩展名。

exclude

  • 类型:String|Array[String]
  • 默认值:'node_modules'

指定需要排除的文件及目录。必须是相对于 options.context 的相对路径。

files

  • 类型:String|Array[String]
  • 默认值:null

指定目录、文件或 globs ,必须是相对于 options.context 的相对路径。 如果是目录则递归查找所有匹配 options.extensions 选项的文件。 如果是文件或 globs 则忽略 options.extensions 选项。

fix

  • 类型:Boolean
  • 默认值:false

启用 ESLint 自动修复特性

小心: 该选项会修改源文件。

formatter

  • 类型:String|Function
  • 默认值:'stylish'

接受一个有单一参数的函数:该参数为 eslint 消息(一个对象)的数组。函数必须返回字符串格式的 output。可以使用官方的 eslint formatters

lintDirtyModulesOnly

  • 类型:Boolean
  • 默认值:false

只对内容修改了的文件进行 lint,启动时跳过 lint 。

threads

  • 类型:Boolean | Number
  • 默认值:false

以线程池方式运行 lint 。线程池大小是自动的,除非你指定一个数值。

错误以及警告

该插件默认会根据 eslint 错误/警告的数量自动调整错误报告(error reporting)。 你也可以通过 emitError emitWarning 强制开启错误报告行为:

emitError

  • 类型:Boolean
  • 默认值:true

总是发送发现的错误 ,设置为 false 以禁用。

emitWarning

  • 类型:Boolean
  • 默认值:true

总是发送发现的警告,设置为 false 以禁用。

failOnError

  • 类型:Boolean
  • 默认值:true

任何错误都会导致模块构建(module build)失败,设置为 false 禁用。

failOnWarning

  • 类型:Boolean
  • 默认值:false

当设置为 true 时,任何警告都会导致模块构建(module build)失败。

quiet

  • 类型:Boolean
  • 默认值:false

设置为 true 后,仅处理和报告错误,忽略警告。

outputReport

  • 类型:Boolean|Object
  • 默认值:false

把错误输出到一个文件,例如在 Jenkins CI 使用 checkstyle xml 文件。

filePath 为绝对路径或者相对于 webpack 配置: output.path 的相对路径。 你可以为输出文件传入不同的 formatter 。 如果没有传入,则使用默认的或已配置的 formatter 。

更新日志

更新日志

License

MIT

EvalSourceMapDevToolPlugin

本插件可以为 source map 的生成提供更好更细粒度的控制。devtool 中的某些配置会自动使用它。

new webpack.EvalSourceMapDevToolPlugin(options);

选项

支持以下选项:

  • test (string|RegExp|array): 默认值为 .js.css,为与给定的模块扩展名相匹配的模块,添加 source map。
  • include (string|RegExp|array): 为与给定路径相匹配的模块,添加 source map。
  • exclude (string|RegExp|array): 排除一些与给定值相匹配的模块,不会为它们生成映射关系。
  • append (string): 将给定的值添加到源代码中,通常是 #sourceMappingURL 注释,[url] 在 source map 文件中将会被替换成 url,值为 false 表示不添加。
  • moduleFilenameTemplate (string): 查看 output.devtoolModuleFilenameTemplate
  • module (boolean): 默认值为 true,表示是否为 loaders 添加 source map。
  • columns (boolean): 默认值为 true,表示是否使用列映射(column mapping)。
  • protocol (string): 默认协议名为 webpack-internal://,允许用户重新定义协议。

示例

以下示例演示了此插件的一些常见用例。

基本用例

可以使用以下代码替换配置选项 devtool: eval-source-map,并使用等效的自定义插件配置:

module.exports = {
  // ...
  devtool: false,
  plugins: [new webpack.EvalSourceMapDevToolPlugin({})],
};

排除 Vendor(第三方库) Maps

下面的代码将排除 vendor.js 包中任何模块 source map 的生成:

new webpack.EvalSourceMapDevToolPlugin({
  exclude: ['vendor.js'],
});

HashedModuleIdsPlugin

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...
});

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.

Usage

Here's an example of how this plugin might be used:

new webpack.ids.HashedModuleIdsPlugin({
  context: __dirname,
  hashFunction: 'sha256',
  hashDigest: 'hex',
  hashDigestLength: 20,
});

HotModuleReplacementPlugin

Hot Module Replacement,除此之外还被称为 HMR。

基本使用

启用 HMR 很容易,且在大多数情况下不需要任何配置。

new webpack.HotModuleReplacementPlugin({
  // Options...
});

HtmlMinimizerWebpackPlugin

npm node deps tests cover chat size

This plugin uses html-minifier-terser to optimize and minify your HTML.

Getting Started

To begin, you'll need to install html-minimizer-webpack-plugin:

npm install html-minimizer-webpack-plugin --save-dev

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: {
    loaders: [
      {
        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
      // `...`
      new HtmlMinimizerPlugin(),
    ],
  },
};

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.

Options

NameTypeDefaultDescription
testString|RegExp|Array<String|RegExp>/\.html(\?.*)?$/iTest to match files against.
includeString|RegExp|Array<String|RegExp>undefinedFiles to include.
excludeString|RegExp|Array<String|RegExp>undefinedFiles to exclude.
parallelBoolean|NumbertrueUse multi-process parallel running to improve the build speed.
minifyFunction|Array<Function>HtmlMinimizerPlugin.htmlMinifierTerserAllows you to override default minify function.
minimizerOptionsObject|Array<Object>{ caseSensitive: true, collapseWhitespace: true, conservativeCollapse: true, keepClosingSlash: true, minifyCSS: true, minifyJS: true, removeComments: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, }Html-minifier-terser optimisations options.

test

Type: 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: 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: 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: 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.

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: Function|Array<Function> Default: HtmlMinimizerPlugin.htmlMinifierTerser

Allows you to override default minify function. By default, plugin uses html-minifier-terser package. Useful for using and testing unpublished versions or forks.

⚠️ Always use require inside minify function when parallel 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: Object|Array<Object> Default: { caseSensitive: true, collapseWhitespace: true, conservativeCollapse: true, keepClosingSlash: true, minifyCSS: true, minifyJS: true, removeComments: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, }

Html-minifier-terser optimisations 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: [],
            };
          },
        ],
      }),
    ],
  },
};

Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.

CONTRIBUTING

License

MIT

HtmlWebpackPlugin

HtmlWebpackPlugin 简化了 HTML 文件的创建,以便为你的 webpack 包提供服务。这对于那些文件名中包含哈希值,并且哈希值会随着每次编译而改变的 webpack 包特别有用。你可以让该插件为你生成一个 HTML 文件,使用 lodash 模板提供模板,或者使用你自己的 loader

安装

npm install --save-dev html-webpack-plugin

基本用法

该插件将为你生成一个 HTML5 文件, 在 body 中使用 script 标签引入你所有 webpack 生成的 bundle。 只需添加该插件到你的 webpack 配置中,如下所示:

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()],
};

这将会生成一个包含以下内容的 dist/index.html 文件:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>webpack App</title>
  </head>
  <body>
    <script src="index_bundle.js"></script>
  </body>
</html>

如果你有多个 webpack 入口,他们都会在已生成 HTML 文件中的 <script> 标签内引入。

如果在 webpack 的输出中有任何 CSS 资源(例如,使用 MiniCssExtractPlugin 提取的 CSS),那么这些资源也会在 HTML 文件 <head> 元素中的 <link> 标签内引入。

配置

获取所有的配置选项,请浏览插件文档

第三方插件

该插件支持第三方插件。详细列表参阅文档

IgnorePlugin

IgnorePlugin prevents the generation of modules for import or require calls matching the regular expressions or filter functions:

Using regular expressions

  • resourceRegExp: A RegExp to test the resource against.
  • contextRegExp: (optional) A RegExp to test the context (directory) against.
new webpack.IgnorePlugin({ resourceRegExp, contextRegExp });

Using filter functions

  • 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;
  },
});

Example of ignoring Moment Locales

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.

ImageMinimizerWebpackPlugin

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.

npm node deps tests cover chat size

Getting Started

This plugin can use 2 tools to compress images:

  • imagemin - optimize your images by default, since it is stable and works with all types of images
  • squoosh - while working in experimental mode with .jpg, .jpeg, .png, .webp, .avif file types.

To begin, you'll need to install image-minimizer-webpack-plugin:

npm install image-minimizer-webpack-plugin --save-dev

Images can be optimized in two modes:

  1. Lossless (without loss of quality).
  2. Lossy (with loss of quality).

Optimize with imagemin

Note:

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');
const { extendDefaultPlugins } = require('svgo');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: 'asset',
      },
    ],
  },
  plugins: [
    new ImageMinimizerPlugin({
      minimizerOptions: {
        // Lossless optimization with custom option
        // Feel free to experiment with options for better result for you
        plugins: [
          ['gifsicle', { interlaced: true }],
          ['jpegtran', { progressive: true }],
          ['optipng', { optimizationLevel: 5 }],
          // Svgo configuration here https://github.com/svg/svgo#configuration
          [
            'svgo',
            {
              plugins: extendDefaultPlugins([
                {
                  name: 'removeViewBox',
                  active: false,
                },
                {
                  name: 'addAttributesToSVGElement',
                  params: {
                    attributes: [{ xmlns: 'http://www.w3.org/2000/svg' }],
                  },
                },
              ]),
            },
          ],
        ],
      },
    }),
  ],
};

Optimize with squoosh

npm install @squoosh/lib --save-dev

Recommended @squoosh/lib options for lossy optimization

For lossy optimization we recommend using the default settings @squoosh/lib. The default values and supported file types for each option can be found in the [codecs.ts](https://github.com/GoogleChromeLabs/squoosh/blob/dev/libsquoosh/src/codecs.ts) file under codecs.

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png)$/i,
        type: 'asset',
      },
    ],
  },
  plugins: [
    new ImageMinimizerPlugin({
      minify: ImageMinimizerPlugin.squooshMinify,
    }),
  ],
};

Recommended squoosh options for lossless optimization

For lossless optimization we recommend using the options listed below in minimizerOptions.encodeOptions.

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png)$/i,
        type: 'asset',
      },
    ],
  },
  plugins: [
    new ImageMinimizerPlugin({
      minify: ImageMinimizerPlugin.squooshMinify,
      minimizerOptions: {
        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,
          },
        },
      },
    }),
  ],
};

ℹ️ If you want to use loader or plugin standalone see sections below, but this is not recommended.

Standalone Loader

Documentation: Using loaders

In your webpack.config.js, add the ImageMinimizerPlugin.loader and specify the asset modules options:

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,
        use: [
          {
            loader: ImageMinimizerPlugin.loader,
            options: {
              severityError: 'warning', // Ignore errors on corrupted images
              minimizerOptions: {
                plugins: ['gifsicle'],
              },
            },
          },
        ],
      },
    ],
  },
};

Standalone Plugin

Documentation: Using plugins

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: 'asset',
      },
    ],
  },
  plugins: [
    // Make sure that the plugin placed after any plugins that added images
    new ImageMinimizerPlugin({
      severityError: 'warning', // Ignore errors on corrupted images
      minimizerOptions: {
        plugins: ['gifsicle'],
      },
      // Disable `loader`
      loader: false,
    }),
  ],
};

Options

Plugin Options

NameTypeDefaultDescription
test{String\/RegExp|Array<String|RegExp>}/.(jpe?g|png|gif|tif|webp|svg|avif)$/iTest to match files against
include{String\/RegExp|Array<String|RegExp>}undefinedFiles to include
exclude{String\/RegExp|Array<String|RegExp>}undefinedFiles to exclude
filter{Function}() => trueAllows filtering of images for optimization
severityError{String}'error'Allows to choose how errors are displayed
minify{Function | Array<Function>}ImageMinimizerPlugin.imageminMinifyAllows to override default minify function
minimizerOptions{Object|Array<Object>}{ plugins: [] }Options for imagemin
loader{Boolean}trueAutomatically adding imagemin-loader
maxConcurrency{Number}Math.max(1, os.cpus().length - 1)Maximum number of concurrency optimization processes in one time
filename{string|Function}'[path][name][ext]'Allows to set the filename for the generated asset. Useful for converting to a webp
deleteOriginalAssets{Boolean}falseAllows to delete the original asset. Useful for converting to a webp and remove original assets

test

Type: String|RegExp|Array<String|RegExp> Default: /\.(jpe?g\|png\|gif\|tif\|webp\|svg\|avif)\$/i

Test to match files against.

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      test: /\.(jpe?g|png|gif|svg)$/i,
    }),
  ],
};

include

Type: String|RegExp|Array<String|RegExp> Default: undefined

Files to include.

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      include: /\/includes/,
    }),
  ],
};

exclude

Type: String|RegExp|Array<String|RegExp> Default: undefined

Files to exclude.

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      exclude: /\/excludes/,
    }),
  ],
};

filter

Type: Function Default: () => true

Allows filtering of images for optimization.

Return true to optimize the image, false otherwise.

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      filter: (source, sourcePath) => {
        // The `source` argument is a `Buffer` of source file
        // The `sourcePath` argument is an absolute path to source
        if (source.byteLength < 8192) {
          return false;
        }

        return true;
      },
    }),
  ],
};

severityError

Type: 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 errors

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      severityError: 'warning',
    }),
  ],
};

minify

Type: Function|Array<Function> Default: ImageMinimizerPlugin.imageminMinify

Allows to override default minify function. By default plugin uses imagemin package. Useful for using and testing unpublished versions or forks.

Аvailable minifiers:

  • ImageMinimizerPlugin.imageminMinify
  • ImageMinimizerPlugin.squooshMinify
Function

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      minify: async (data, minimizerOptions) => {
        const [[, input]] = Object.entries(data);

        let result;

        try {
          result = await minifyAndReturnBuffer(input);
        } catch (error) {
          // Return original input if there was an error
          return { data: input, errors: [error] };
        }

        return { data: result, warnings: [], errors: [] };
      },
      minimizerOptions: {},
    }),
  ],
};
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

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      minify: [
        ImageMinimizerPlugin.imageminMinify,
        (data, minimizerOptions) => {
          const [[, input]] = Object.entries(data);

          let result;

          try {
            result = minifyAndReturnBuffer(input);
          } catch (error) {
            // Return original input if there was an error
            return { data: input, errors: [error] };
          }

          return { data: result, warnings: [], errors: [] };
        },
      ],
      minimizerOptions: [
        // Options for the first function (ImageMinimizerPlugin.imageminMinify)
        {
          plugins: ['gifsicle', 'mozjpeg', 'pngquant', 'svgo'],
        },
        // Options for the second function
        {},
      ],
    }),
  ],
};

minimizerOptions

Type: Object|Array<Object> Default: { plugins: [] }

Options for minify functions. imagemin is default minify function.

More information and examples here.

Object

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      minimizerOptions: {
        plugins: [
          // Name
          'gifsicle',
          // Name with options
          ['mozjpeg', { quality: 80 }],
          // Full package name
          [
            'imagemin-svgo',
            {
              plugins: [
                {
                  removeViewBox: false,
                },
              ],
            },
          ],
          [
            // Custom package name
            'nonstandard-imagemin-package-name',
            { myOptions: true },
          ],
        ],
      },
    }),
  ],
};
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

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      minify: [
        ImageMinimizerPlugin.imageminMinify,
        async (data, minimizerOptions) => {
          const [[, input]] = Object.entries(data);

          let result;

          try {
            result = await minifyAndReturnBuffer(input);
          } catch (error) {
            // Return original input if there was an error
            return { data: input, errors: [error] };
          }

          return { data: result, warnings: [], errors: [] };
        },
      ],
      minimizerOptions: [
        // Options for the first function (ImageMinimizerPlugin.imageminMinify)
        {
          plugins: ['gifsicle', 'mozjpeg', 'pngquant', 'svgo'],
        },
        // Options for the second function
        {},
      ],
    }),
  ],
};

loader

Type: Boolean Default: true

Automatically adding imagemin-loader.

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      loader: false,
    }),
  ],
};

maxConcurrency

Type: Number Default: Math.max(1, os.cpus().length - 1)

Maximum number of concurrency optimization processes in one time.

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      maxConcurrency: 3,
    }),
  ],
};

filename

Type: String|Function Default: '[path][name][ext]'

Allows to set the filename for the generated asset. Useful for converting to a webp. Supported values see in webpack template strings, File-level section.

String

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    // Images are converted to `webp` and the original assets have been kept
    new ImageMinimizerPlugin({
      test: /\.(png)$/i,
      filename: '[path][name].webp',
      minimizerOptions: {
        plugins: ['imagemin-webp'],
      },
    }),
  ],
};
Function

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    // Images are converted to `webp` and the original assets have been kept
    new ImageMinimizerPlugin({
      test: /\.(png)$/i,
      filename: (pathData, assetInfo) => {
        if (/imageLg/i.test(pathData.filename)) {
          return './bigImages/[path][name].webp';
        }

        return '[path][name].webp';
      },
      minimizerOptions: {
        plugins: ['imagemin-webp'],
      },
    }),
  ],
};
Converting to webp using ImageMinimizerPlugin.squooshMinify

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
/*
const defaultTargets = {
  ".png": "oxipng",
  ".jpg": "mozjpeg",
  ".jpeg": "mozjpeg",
  ".jxl": "jxl",
  ".webp": "webp",
  ".avif": "avif",
};
*/

module.exports = {
  plugins: [
    // Images are converted to `webp` and the original assets have been kept
    new ImageMinimizerPlugin({
      test: /\.(png)$/i,
      filename: '[path][name].webp',
      minify: ImageMinimizerPlugin.squooshMinify,
      minimizerOptions: {
        targets: {
          '.png': 'webp',
        },
      },
    }),
  ],
};

deleteOriginalAssets

Type: Boolean Default: false

Allows to remove original assets. Useful for converting to a webp and remove original assets

ℹ️ Doesn't make sense if you haven't changed the original value of the filename option

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    // Images are converted to `webp` and the original assets have been removed
    new ImageMinimizerPlugin({
      test: /\.(png)$/i,
      deleteOriginalAssets: true,
      filename: '[path][name].webp',
      minimizerOptions: {
        plugins: ['imagemin-webp'],
      },
    }),
  ],
};

To generate and compress the original assets:

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    // And the original assets will be compressed
    new ImageMinimizerPlugin({
      test: /\.(png)$/i,
      minimizerOptions: {
        plugins: ['pngquant'],
      },
    }),
    // Images are converted to `webp` and the original assets have been removed
    new ImageMinimizerPlugin({
      test: /\.(png)$/i,
      deleteOriginalAssets: false,
      filename: '[path][name].webp',
      minimizerOptions: {
        plugins: ['imagemin-webp'],
      },
    }),
  ],
};

Loader Options

NameTypeDefaultDescription
filter{Function}undefinedAllows filtering of images for optimization
severityError{String}'error'Allows to choose how errors are displayed
minify{Function | Array<Function>}ImageMinimizerPlugin.imageminMinifyAllows to override default minify function
minimizerOptions{Object|Array<Object>}{ plugins: [] }Options for imagemin
filename{string|Function}'[path][name][ext]'Allows to set the filename for the generated asset. Useful for converting to a webp
deleteOriginalAssets{Boolean}falseAllows to delete the original asset. Useful for converting to a webp and remove original assets

filter

Type: Function Default: () => true

Allows filtering of images for optimization.

Return true to optimize the image, false otherwise.

webpack.config.js

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: {
              cache: true,
              filter: (source, sourcePath) => {
                // The `source` argument is a `Buffer` of source file
                // The `sourcePath` argument is an absolute path to source
                if (source.byteLength < 8192) {
                  return false;
                }

                return true;
              },
              minimizerOptions: {
                plugins: ['gifsicle'],
              },
            },
          },
        ],
      },
    ],
  },
};

severityError

Type: 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 errors

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,
        use: [
          {
            loader: ImageMinimizerPlugin.loader,
            options: {
              severityError: 'warning',
              minimizerOptions: {
                plugins: ['gifsicle'],
              },
            },
          },
        ],
      },
    ],
  },
};

minify

Type: Function|Array<Function> Default: ImageMinimizerPlugin.imageminMinify

Allows to override default minify function. By default plugin uses imagemin package. Useful for using and testing unpublished versions or forks.

Аvailable minifiers:

  • ImageMinimizerPlugin.imageminMinify
  • ImageMinimizerPlugin.squooshMinify
Function

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,
        use: [
          {
            loader: ImageMinimizerPlugin.loader,
            options: {
              minify: async (data, minimizerOptions) => {
                const [[, input]] = Object.entries(data);

                let result;

                try {
                  result = await minifyAndReturnBuffer(input);
                } catch (error) {
                  // Return original input if there was an error
                  return { data: input, errors: [error] };
                }

                return { data: result, warnings: [], errors: [] };
              },
              minimizerOptions: {},
            },
          },
        ],
      },
    ],
  },
};
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

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: {
              minify: [
                ImageMinimizerPlugin.imageminMinify,
                async (data, minimizerOptions) => {
                  const [[, input]] = Object.entries(data);

                  let result;

                  try {
                    result = await minifyAndReturnBuffer(input);
                  } catch (error) {
                    // Return original input if there was an error
                    return { data: input, errors: [error] };
                  }

                  return { data: result, warnings: [], errors: [] };
                },
              ],
              minimizerOptions: [
                // Options for the first function (ImageMinimizerPlugin.imageminMinify)
                {
                  plugins: ['gifsicle', 'mozjpeg', 'pngquant', 'svgo'],
                },
                // Options for the second function
                {},
              ],
            },
          },
        ],
      },
    ],
  },
};

minimizerOptions

Type: Object|Array<Object> Default: { plugins: [] }

Options for minify functions. imagemin is default minify function.

More information and examples here.

Object

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,
        use: [
          {
            loader: ImageMinimizerPlugin.loader,
            options: {
              minimizerOptions: {
                plugins: [
                  ['gifsicle', { interlaced: true, optimizationLevel: 3 }],
                ],
              },
            },
          },
        ],
      },
    ],
  },
};
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

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: {
              minify: [
                ImageMinimizerPlugin.imageminMinify,
                async (data, minimizerOptions) => {
                  const [[, input]] = Object.entries(data);

                  let result;

                  try {
                    result = await minifyAndReturnBuffer(input);
                  } catch (error) {
                    // Return original input if there was an error
                    return { data: input, errors: [error] };
                  }

                  return { data: result, warnings: [], errors: [] };
                },
              ],
              minimizerOptions: [
                // Options for the first function (ImageMinimizerPlugin.imageminMinify)
                {
                  plugins: [
                    ['gifsicle', { interlaced: true, optimizationLevel: 3 }],
                  ],
                },
                // Options for the second function
                {},
              ],
            },
          },
        ],
      },
    ],
  },
};

filename

Type: String|Function Default: '[path][name][ext]'

Allows to set the filename for the generated asset. Useful for converting to a webp. Supported values see in webpack template strings, File-level section.

String

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif)$/i,
        use: [
          {
            test: /\.(jpe?g|png|gif|svg)$/i,
            type: 'asset',
          },
          {
            loader: ImageMinimizerPlugin.loader,
            options: {
              filename: '[path][name].webp',
              minimizerOptions: {
                plugins: ['imagemin-webp'],
              },
            },
          },
        ],
      },
    ],
  },
};
Function

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif)$/i,
        use: [
          {
            test: /\.(jpe?g|png|gif|svg)$/i,
            type: 'asset',
          },
          {
            loader: ImageMinimizerPlugin.loader,
            options: {
              filename: (pathData, assetInfo) => {
                if (/imageLg/i.test(pathData.filename)) {
                  return './bigImages/[path][name].webp';
                }

                return '[path][name].webp';
              },
              minimizerOptions: {
                plugins: ['imagemin-webp'],
              },
            },
          },
        ],
      },
    ],
  },
};

deleteOriginalAssets

Type: Boolean Default: false

Allows to keep the original asset. Useful for converting to a webp and remove original assets.

ℹ️ Doesn't make sense if you haven't changed the original value of the filename option

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png)$/i,
        use: [
          {
            test: /\.(jpe?g|png|gif|svg)$/i,
            type: 'asset',
          },
          {
            loader: ImageMinimizerPlugin.loader,
            options: {
              // PNG images are converted to WEBP, and the originals will keep
              deleteOriginalAssets: false,
              filename: '[path][name].webp',
              minimizerOptions: {
                plugins: ['imagemin-webp'],
              },
            },
          },
        ],
      },
    ],
  },
};

Additional API

imageminNormalizeConfig(config)

The function normalizes configuration (converts plugins names and options to Functions) for using in imagemin package directly.

const imagemin = require('imagemin');
const { imageminNormalizeConfig } = require('image-minimizer-webpack-plugin');
const imageminConfig = imageminNormalizeConfig({
  plugins: [
    'jpegtran',
    [
      'pngquant',
      {
        quality: [0.6, 0.8],
      },
    ],
  ],
});

/*
  console.log(imageminConfig);
  =>
  {
    plugins: [Function, Function],
    pluginsMeta: [
      { name: "imagemin-jpegtran", version: "x.x.x", options: {} },
      { name: "imagemin-pngquant", version: "x.x.x", options: { quality: [0.6, 0.8] }
    ]
  }
*/

(async () => {
  const files = await imagemin(['images/*.{jpg,png}'], {
    destination: 'build/images',
    plugins: imageminConfig.plugins,
  });

  console.log(files);
  // => [{data: <Buffer 89 50 4e …>, path: 'build/images/foo.jpg'}, …]
})();

Examples

Optimize images based on size

You can use difference options (like progressive/interlaced and etc) based on image size (example - don't do progressive transformation for small images).

What is progressive image? Answer here.

webpack.config.js

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  minimizer: [
    new ImageMinimizerPlugin({
      // Only apply this one to files equal to or over 8192 bytes
      filter: (source) => {
        if (source.byteLength >= 8192) {
          return true;
        }

        return false;
      },
      minimizerOptions: {
        plugins: [['jpegtran', { progressive: true }]],
      },
    }),
    new ImageMinimizerPlugin({
      // Only apply this one to files under 8192
      filter: (source) => {
        if (source.byteLength < 8192) {
          return true;
        }

        return false;
      },
      minimizerOptions: {
        plugins: [['jpegtran', { progressive: false }]],
      },
    }),
  ],
};

Optimize and transform images to webp

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      minimizerOptions: {
        plugins: ['pngquant'],
      },
    }),
    new ImageMinimizerPlugin({
      deleteOriginalAssets: false,
      filename: '[path][name].webp',
      minimizerOptions: {
        plugins: ['imagemin-webp'],
      },
    }),
  ],
};

Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.

CONTRIBUTING

License

MIT

InstallWebpackPlugin

npm deps test coverage chat

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

Usage

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,
  });
],

Options

dependencies

Type: Object

Dependencies related options.

peer

Type: Boolean

Default: true

Install missing peer dependencies.

plugins: [
  new InstallPlugin({
    dependencies: {
      peer: true,
    }
  }),
],

packageManager

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

Type: 'npm' | 'yarn' | 'pnpm'

Name of package manager to use for installing dependencies.

options

Type: Object

Package manager related options.

arguments

Type: Array

Provide custom arguments to use with package manager.

plugins: [
  new InstallPlugin({
      packageManager: {
        type: 'npm',
        options: {
          arguments: ['--ignore-scripts']
        }
      }
    },
  }),
],

dev

Type: Boolean

Default: false

Install as development dependencies.

plugins: [
  new InstallPlugin({
      packageManager: {
        type: 'npm',
        options: {
          dev: true,
        }
      }
    },
  }),
],

quiet

Type: Boolean

Default: false

Reduce the amount of console logging.

plugins: [
  new InstallPlugin({
      packageManager: {
        type: 'npm',
        options: {
          quiet: true,
        }
      }
    },
  }),
],

prompt

Type: Boolean

Default: true

Show a prompt to confirm installation.

plugins: [
  new InstallPlugin({
      prompt: true,
    },
  }),
],

Demo

install-webpack-plugin demo

Features

  • Works with webpack ^v5.0.0.
  • Auto-installs .babelrc plugins & presets.
  • Supports both ES5 & ES6 Modules. (e.g. require, import)
  • Supports Namespaced packages. (e.g. @cycle/dom)
  • Supports Dot-delimited packages. (e.g. lodash.capitalize)
  • Supports CSS imports. (e.g. @import "~bootstrap")
  • Supports webpack loaders. (e.g. babel-loader, file-loader, etc.)
  • Supports inline webpack loaders. (e.g. require("bundle?lazy!./App")
  • Auto-installs missing peerDependencies. (e.g. @cycle/core will automatically install rx@*)
  • Supports webpack's resolve.alias & resolve.root configuration. (e.g. require("react") can alias to react-lite)

Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.

CONTRIBUTING

插件

Webpack 拥有丰富的插件接口。webpack 自身的大部分功能都使用这些插件接口。这使得 webpack 很灵活

插件描述
BannerPlugin为每个 chunk 文件头部添加 banner
CommonsChunkPlugin提取 chunk 之间的公共模块用以共享
CompressionWebpackPlugin准备好用 Content-Encoding 格式传送的压缩版资源包
ContextReplacementPlugin重写 require 表达式的推断上下文
CopyWebpackPlugin复制某个文件或整个文件夹到生成目录中
DefinePlugin允许创建一个在编译时可配置的全局常量
DllPlugin拆分 bundles,从而大幅减少构建时间
EnvironmentPluginprocess.env 键上使用 DefinePlugin 的简写方式
EslintWebpackPluginwebpack 的 ESLint 插件
HotModuleReplacementPlugin启用热更新 (HMR)
HtmlWebpackPlugin快速创建 HTML 文件来服务 bundles
IgnorePlugin从 bundles 包中移除某些模块
LimitChunkCountPlugin设置 chunk 的最小/最大限制,以便更好的控制 chunk
MinChunkSizePlugin确保 chunk 大小在指定限制之上
MiniCssExtractPlugin为每一个包含了 CSS 的 JS 文件创建一个 CSS 文件
NoEmitOnErrorsPlugin出现编译错误时,跳过输出阶段
NormalModuleReplacementPlugin替换与正则表达式匹配的资源
NpmInstallWebpackPlugin开发时自动安装缺少的依赖
ProgressPlugin报告编译进度
ProvidePlugin使用模块但无需使用 import/require
SourceMapDevToolPlugin对 source map 进行更细颗粒度的控制
EvalSourceMapDevToolPlugin对 eval source map 进行更细颗粒度的控制
TerserPlugin在你的项目中使用 Terser 插件来压缩 JS

查找更多第三方插件,请参阅 awesome-webpack

Internal webpack plugins

This is a list of plugins which are used by webpack internally.

Categories of internal plugins:

environment

Plugins affecting the environment of the compiler.

NodeEnvironmentPlugin

webpack.node.NodeEnvironmentPlugin()

Applies Node.js style filesystem to the compiler.

compiler

Plugins affecting the compiler

MemoryCachePlugin

MemoryCachePlugin()

Adds a cache to the compiler, where modules are cached in memory.

ProgressPlugin

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

RecordIdsPlugin()

Saves and restores module and chunk ids from records.

entry

Plugins, which add entry chunks to the compilation.

EntryPlugin

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

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).

output

JsonpTemplatePlugin

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.

NodeTemplatePlugin

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

LibraryTemplatePlugin(name, target)

The entries chunks are decorated to form a library name of type type.

WebWorkerTemplatePlugin

webworker/WebWorkerTemplatePlugin(options)

Chunks are loaded by importScripts. Else it's similar to JsonpTemplatePlugin.

options are the output options.

EvalDevToolModulePlugin

Decorates the module template by wrapping each module in a eval annotated with // @sourceURL.

SourceMapDevToolPlugin

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

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.

source

Plugins affecting the source code of modules.

APIPlugin

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.

CompatibilityPlugin

Currently useless. Ensures compatibility with other module loaders.

ConstPlugin

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:

  • The ones performed by Terser
  • The ones performed by webpack

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

ProvidePlugin(name, request)

If name is used in a module it is filled by a module loaded by require(<request>).

NodeStuffPlugin

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.

RequireJsStuffPlugin

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.

NodeSourcePlugin

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.

NodeTargetPlugin

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.

AMDPlugin

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.

CommonJsPlugin

dependencies/CommonJsPlugin

Provides CommonJs-style require to modules.

RequireContextPlugin

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.

RequireEnsurePlugin

dependencies/RequireEnsurePlugin()

Provides require.ensure.

RequireIncludePlugin

dependencies/RequireIncludePlugin()

Provides require.include.

DefinePlugin

DefinePlugin(definitions)

Define constants for identifier.

definitions is an object.

optimize

请注意在 webpack.optimize 命名空间下的所有插件应该只在 mode 设置为 'none' 时使用。否则你将会在插件被两次使用时遇到麻烦。

LimitChunkCountPlugin

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.

MergeDuplicateChunksPlugin

optimize/MergeDuplicateChunksPlugin()

Chunks with the same modules are merged.

RemoveEmptyChunksPlugin

optimize/RemoveEmptyChunksPlugin()

Modules that are included in every parent chunk are removed from the chunk.

MinChunkSizePlugin

optimize/MinChunkSizePlugin(minChunkSize)

Merges chunks until each chunk has the minimum size of minChunkSize.

ModuleConcatenationPlugin

请查看 ModuleConcatenationPlugin 页面 获取更多内容。

FlagIncludedChunksPlugin

optimize/FlagIncludedChunksPlugin()

Adds chunk ids of chunks which are included in the chunk. This eliminates unnecessary chunk loads.

RealContentHashPlugin

optimize/RealContentHashPlugin()

When optimization.realContentHash option is enabled, webpack will apply RealContentHashPlugin to compiler internally.

Hook

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
  });
});

JsonMinimizerWebpackPlugin

npm node deps tests cover chat size

This plugin uses JSON.stringify() to minify your JSON.

Getting Started

To begin, you'll need to install json-minimizer-webpack-plugin:

npm install json-minimizer-webpack-plugin --save-dev

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.

Options

NameTypeDefaultDescription
testString|RegExp|Array<String|RegExp>/\.json(\?.*)?$/iTest to match files against.
includeString|RegExp|Array<String|RegExp>undefinedFiles to include.
excludeString|RegExp|Array<String|RegExp>undefinedFiles to exclude.
minimizerOptionsObject{ replacer: null, space: null }JSON.stringify() options.

test

Type: 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: 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: 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: Object Default: { replacer: null, space: null }

JSON.stringify() options.

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new JsonMinimizerPlugin({
        minimizerOptions: {
          space: '\t',
        },
      }),
    ],
  },
};

Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.

CONTRIBUTING

License

MIT

LimitChunkCountPlugin

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...
});

Options

The following options are supported:

maxChunks

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,
    }),
  ],
};

minChunkSize

Keeping chunk size above the specified limit is no longer a feature of this plugin. Use MinChunkSizePlugin instead.

Usage via CLI

This plugin and it's options can also be invoked via the CLI:

webpack --optimize-max-chunks 15

MinChunkSizePlugin

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
});

Usage via CLI

This plugin and it's options can also be invoked via the CLI:

webpack --optimize-min-chunk-size 10000

MiniCssExtractPlugin

npm node deps tests coverage chat size

本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载。

本插件基于 webpack v5 的新特性构建,并且需要 webpack 5 才能正常工作。

与 extract-text-webpack-plugin 相比:

  • 异步加载
  • 没有重复的编译(性能)
  • 更容易使用
  • 特别针对 CSS 开发

快速开始

首先,你需要安装 mini-css-extract-plugin

npm install --save-dev mini-css-extract-plugin

建议 mini-css-extract-plugincss-loader 一起使用。

之后将 loader 与 plugin 添加到你的 webpack 配置文件中。 例如:

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"],
      },
    ],
  },
};

⚠️ 注意,如果你从 webpack 入口处导入 CSS 或者在 初始 chunk 中引入 style, mini-css-extract-plugin 则不会将这些 CSS 加载到页面中。请使用 html-webpack-plugin 自动生成 link 标签或者在创建 index.html 文件时使用 link 标签。

⚠️ source map 只在 source-map/nosources-source-map/hidden-nosources-source-map/hidden-source-map 值情况下起作用,因为 CSS 仅支持带有 sourceMappingURL 注释的 source map (例如 //# sourceMappingURL=style.css.map)。如果你需要将 devtool 设置为其他值,你可以使用 css-loader 中的 sourceMap: true 来启用提取并生成 CSS 的 source map。

选项

Plugin Options

选项名类型默认值描述
filename{String|Function}[name].css此选项决定了输出的每个 CSS 文件的名称
chunkFilename{String|Function}based on filename此选项决定了非入口的 chunk 文件名称
ignoreOrder{Boolean}false移除 Order 警告
insert{String|Function}var head = document.getElementsByTagName("head")[0];head.appendChild(linkTag);在指定位置将 非初始(由 async 修饰) 的 CSS chunk 插入 link 标签
attributes{Object}{}非初始(由 async 修饰) 的 CSS chunk 所处的 link 标签添加自定义属性
linkType{String|Boolean}text/css允许使用自定义 link 类型加载异步 chunk
runtime{Boolean}true允许启动/禁用 runtime 生成
experimentalUseImportModule{Boolean}undefined使用实验性的 webpack API 来执行模块,而非子代编译器

filename

类型:String|Function 默认值:[name].css

此选项决定了输出的每个 CSS 文件的名称。

机制类似于 output.filename

chunkFilename

类型:String|Function 默认值:based on filename

chunkFilename 设置为 function,仅在 webpack@5 下可用。

此选项决定了非入口的 chunk 文件名称

机制类似于 output.chunkFilename

ignoreOrder

类型:Boolean 默认值:false

移除 Order 警告 具体细节请参阅示例

insert

类型:String|Function 默认值:document.head.appendChild(linkTag);

⚠️ 仅对 非初始(由 async 修饰) chunk 有效。

默认情况下,mini-css-extract-plugin 会将 styles(<link> 元素)附加到当前 windowdocument.head 中。

但在某些情况下,可能需要对附加的目标进行精细化管理,甚至延迟 link 元素的插入。 例如,当你在 iframe 中运行应用程序异步加载样式时,就属于此情况。 对于此类情况,insert 可被配置为函数或自定义的选择器。

如果附加目标为 iframe,请确保父文档有足够的访问权限进入 frame document,并将元素附加到它上面。

String

允许设置自定义的 query selector。 新的 <link> 元素将被插入到找到的 item 之后。

webpack.config.js

new MiniCssExtractPlugin({
  insert: "#some-element",
});

找到 id 为 some-element 的元素,在它之后插入新的 <link> 元素。

Function

允许覆盖默认行为,并在任意位置插入样式。

⚠ 注意,这段代码将与你的应用程序一起在浏览器中运行。由于并非所有浏览器都支持 ESMA 特性,如 letconstarrow function expression 等,我们建议只使用 ECMA 5 的特性和语法。

insert 函数被序列化为字符串并传递给插件。这意味着它将无法访问 webpack 配置模块的作用域。

webpack.config.js

new MiniCssExtractPlugin({
  insert: function (linkTag) {
    var reference = document.querySelector("#some-element");
    if (reference) {
      reference.parentNode.insertBefore(linkTag, reference);
    }
  },
});

找到 id 为 some-element 的元素,在它之后插入新的 <link> 元素。

attributes

类型:Object 默认值:{}

⚠️ 仅对 非初始(由 async 修饰) chunk 有效。

如果定义了此选项,mini-css-extract-plugin 将把指定的属性和值附加到 <link> 元素上。

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"],
      },
    ],
  },
};

注意:它只适用于动态加载的 css chunk,如果你想修改 html 文件内的链接属性,请使用 html-webpack-plugin

linkType

类型:String|Boolean 默认值:text/css

此选项运行使用自定义链接类型加载异步 chunk,例如 <link type="text/css" ...>

String

可选值: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 禁用 link 的 type 属性

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: Boolean Default: true

允许开启/禁用 runtime 生成。 CSS 仍将被提取,并可用于自定义加载方法。 例如,你可以使用 assets-webpack-plugin 来检索它们,然后当需要时使用你自己的 runtime 代码下载静态资源。

设置为 true 以跳过。

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

类型:Boolean 默认值:undefined

如果没有显式启用,则默认启用(即可以通过 truefalse 显式控制该配置),并且新 API 处于可用状态(webpack 版本至少为 5.52.0)。 布尔值在 5.33.2 版本后可用,但是你需要启用 experiments.executeModule(webpack 5.52.0 版本不需要)。

使用新的 webpack API 来执行模块而不是子编译器。 这大大提高了性能和内存使用。

当与 experiments.layers 相结合时,添加了一个 layer 选项到 loader 配置项中,以指定 CSS 执行的 layer。

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // `>= 5.52.0` 版本的 webpack 不需要该配置,因为该配置项默认启用
      // 仅 `>= 5.33.2 & <= 5.52.0` 版本的 webpack 需要该配置
      // 对于 `<= 5.33.2` 版本的 webpack 不可用/不安全
      experimentalUseImportModule: true,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Loader 选项

名称类型默认值描述
publicPath{String|Function}webpackOptions.output.publicPath为图片、文件等外部资源指定一个自定义的公共路径。
emit{Boolean}true如果设为 false,插件将会提取 CSS 但不会 生成文件
esModule{Boolean}true使用 ES modules 语法

publicPath

类型:String|Function 默认值:webpackOptions.output 选项中的 publicPath

为 CSS 内的图片、文件等外部资源指定一个自定义的公共路径。 机制类似于 output.publicPath

String

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // 类似于 webpackOptions.output 中的选项
      // 所有选项都是可选的
      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({
      // 类似于 webpackOptions.output 中的选项
      // 所有选项都是可选的
      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

类型:Boolean 默认值:true

如果设置为 true,会发送一个文件(向文件系统中写入一个文件)。如果设置为 false,该插件将会提取 CSS 但是 不会 发送文件。 禁用该配置对服务侧的包比较有用。

esModule

类型:Boolean 默认值:true

默认情况下 mini-css-extract-plugin 将会生成使用 ES 模块语法的 JS 模块。 在某些情况下,使用 ES 模块是有益的,比如:module concatenationtree shaking

你可以使用以下方式启用 CommonJS 语法:

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",
        ],
      },
    ],
  },
};

示例

推荐

推荐 production 环境的构建将 CSS 从你的 bundle 中分离出来,这样可以使用 CSS/JS 文件的并行加载。 这可以通过使用 mini-css-extract-plugin 来实现,因为它可以创建单独的 CSS 文件。 对于 development 模式(包括 webpack-dev-server),你可以使用 style-loader,因为它可以使用多个 标签将 CSS 插入到 DOM 中,并且反应会更快。

i 不要同时使用 style-loadermini-css-extract-plugin

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";

module.exports = {
  module: {
    rules: [
      {
        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",
        ],
      },
    ],
  },
};

Named export for CSS Modules

⚠ 命名会被修改为 camelCase 的形式。

⚠ 不允许在 css 的 class name 中使用 JavaScript 关键字。

⚠ 应启用 css-loader 中的 esModule 以及 modules.namedExport 选项。

styles.css

.foo-baz {
  color: red;
}
.bar {
  color: blue;
}

index.js

import { fooBaz, bar } from "./styles.css";

console.log(fooBaz, bar);

你可以按照如下配置启用 ES 模块命名导出:

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 选项为函数

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // 类似于 webpackOptions.output 中的选项
      // 所有选项都是可选的
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: (resourcePath, context) => {
                // publicPath 是资源相对于上下文的相对路径
                // 例如:对于 ./css/admin/main.css publicPath 将会是 ../../
                // 而对于 ./css/main.css publicPath 将会是 ../
                return path.relative(path.dirname(resourcePath), context) + '/';
              },
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

高级配置示例

此插件不能与 loader 链中的 style-loader 一同使用。

这是一个在 development 构建中使用 HMR 并且在 production 构建中将样式文件提取到独立文件中的示例。

(为了更加清楚的表达,省略了 Loader 的选项,以适应需要。)

如果你使用的是 webpack-dev-server,那么就无需使用 HotModuleReplacementPlugin plugin。 webpack-dev-server 使用 hot 选项决定是否启用/禁用 HMR。

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",
        ],
      },
    ],
  },
};

模块热更新 (HMR)

注意:在 webpack 5 中 HMR 已自动支持。无需配置。你可以跳过以下内容:

mini-css-extract-plugin 支持在开发中热重载实际的 CSS 文件。 我们提供了一些选项来启动标准 stylesheets 和本地范围内 CSS 和 CSS modules 的 HMR 支持。 以下是 mini-css 用于启动 HMR CSS modules 的示例配置。

如果你使用的是 webpack-dev-server,那么你无需使用 HotModuleReplacementPlugin 插件。 webpack-dev-server 使用 hot 选项来控制启用/禁用 HMR。

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",
        ],
      },
    ],
  },
};

生产模式压缩

为了压缩输出文件,请使用类似于 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(),
    ],
  },
};

这将只在生产模式下启用 CSS 压缩优化。如果你需要在开发模式下使用,请设置 optimization.minimize 选项为 true。

使用预加载或内联 CSS

运行时代码通过 <link> 或者<style> 标签检测已经添加的 CSS。 当在服务端注入 CSS 代码 以及做 SSR 时将会很有用。 <link> 标签的 href 属性必须与将要被加载的 CSS chunk 的 URL 相匹配。 data-href 属性也可以被用在 <link><style> 标签中 使用内联 CSS 时,必须使用 data-href 属性。

提取所有的 CSS 到一个文件中

用过使用 optimization.splitChunks.cacheGroups 选项,所有的 CSS 可以被提取到一个 CSS 文件中。

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"],
      },
    ],
  },
};

请注意在 webpack 5 中应该使用 type 而不是 test,否则将会生成 .js 文件而不是 .css。这是因为 test 不知道应该去掉哪个模块(在这种情况下,它不会检测到 .js 应该被删除)。

基于入口提取 CSS

你可以基于 webpack 的入口名称提取 CSS。 当你使用路由动态加载但是想要通过入口加载对应的 CSS 文件时这将会非常有用。 这样也避免了 ExtractTextPlugin 造成的 CSS 重复复制问题。

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"],
      },
    ],
  },
};

文件名选项设置为函数

使用 filename 选项,你可以使用 chunk 数据来定制文件名。 这点在处理多个入口,并且希望对给定的 入口/chunk 文件进行更多处理时,非常有用。 下面示例中,我们使用 filename 将生成的 css 输出到不同的目录中。

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"],
      },
    ],
  },
};

长期缓存

使用 filename: "[contenthash].css" 启动长期缓存。根据需要添加 [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"],
      },
    ],
  },
};

移除 Order 警告

对于通过使用 scoping 或命名约定来解决 css order 的项目,可以通过将插件的 ignoreOrder 选项设置为 true 来禁用 css order 警告。

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: [
              Self.loader,
              "css-loader",
              {
                loader: "sass-loader",
                options: {
                  additionalData: `@use 'dark-theme/vars' as vars;`,
                },
              },
            ],
          },
          {
            use: [
              Self.loader,
              "css-loader",
              {
                loader: "sass-loader",
                options: {
                  additionalData: `@use 'light-theme/vars' as vars;`,
                },
              },
            ],
          },
        ],
      },
    ],
  },
  plugins: [
    new Self({
      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>

媒体查询插件

如果您想从 CSS 文件中提取媒体查询(因为移动用户不需要加载电脑或平板专用的 CSS ),应使用以下插件之一:

贡献

如果你还没有阅读过我们的贡献指南,请花一点时间阅读它。

CONTRIBUTING

License

MIT

ModuleConcatenationPlugin

在过去,webpack 打包时的一个权衡是,打包中的每个模块都会被包裹在单独的函数闭包中。这些包裹的函数使得 JavaScript 在浏览器中执行速度变慢。相比之下,像 Closure Compiler 和 RollupJS 这样的工具会将所有模块的作用域“提升”或合并到一个闭包中,从而使得代码在浏览器中执行速度更快。

此插件将在 webpack 中启用相同的合并行为。默认情况下,此插件在 生产模式 下已启用,在其他情况下则禁用。将 optimization.concatenateModules 选项 设置为 false 即可覆盖在生产模式下的默认优化。手动添加 ModuleConcatenationPlugin 或使用 optimization.concatenateModules 选项可以在其他模式下启用合并行为:

new webpack.optimize.ModuleConcatenationPlugin();

这种合并行为被称为“作用域提升”。

作用域提升是 ECMAScript 模块语法特别支持的一个功能。因此,webpack 可能会根据使用的模块类型和 其他条件 回退到普通的打包方式。

优化 bailout

正如文章所解释的,webpack 尝试实现部分作用域提升。它会将模块合并到一个单一的作用域中,但并非在所有情况下都能做到。如果 webpack 无法合并一个模块,则有两种替代方案:阻止与创建新组。阻止意味着该模块必须在自己的作用域中;创建新组意味着会创建一个新的模块组。以下条件决定了不同的输出:

条件输出
没有 ES6 模块阻止
从非导入导入创建新组
从其他 chunk 导入创建新组
被其他多个模块分组导入创建新组
import() 语法导入创建新组
ProvidePlugin 影响或使用 module阻止
接受 HMR创建新组
使用 eval()阻止
在多个 chunk 中阻止
export * from "cjs-module"阻止

模块分组算法

下面的伪 JavaScript 代码解释了该算法:

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;
}

调试优化 bailout

如果使用的是 webpack CLI,使用 --stats-optimization-bailout 标志将显示出现 bailout 的原因;如果使用的是 webpack 配置,则需要向 stats 对象添加以下内容:

module.exports = {
  //……
  stats: {
    // 此配置将显示出现 bailout 的原因
    optimizationBailout: true,
  },
};

ModuleFederationPlugin

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,
    }),
  ],
};

Options

runtime

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',
    }),
  ],
};

Specify package versions

There are three ways to specify the versions of shared libraries.

Array syntax

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'],
    }),
  ],
};

Object syntax

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',
      },
    }),
  ],
};

Object syntax with sharing hints

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,
        },
      },
    }),
  ],
};

Sharing hints

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

The required version of the package.

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.

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).

version

false | string

The version of the provided module. It allows webpack to replace lower matching versions, but not higher.

Additional examples

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
        },
      },
    }),
  ],
};

NoEmitOnErrorsPlugin

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()],
};

NormalModuleReplacementPlugin

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);

注意,resourceRegExp 是针对你在代码中编写的请求进行测试的,而不是解析的资源。例如,当你写了一段 import sum from './sum' 的代码时,'./sum' 将会被用来测试而不是 './sum.js'

Basic Example

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'
);

Advanced Example

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}`
          );
        }
      ),
    ],
  };
};

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'

PrefetchPlugin

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);

Options

  • context: An absolute path to a directory
  • request: A request string for a normal module

ProfilingPlugin

Generate 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.

Options

  • outputPath: An absolute path to a custom output file (json)

Usage: default

new webpack.debug.ProfilingPlugin();

Usage: custom outputPath

new webpack.debug.ProfilingPlugin({
  outputPath: path.join(__dirname, 'profiling/profileEvents.json'),
});

In order to view the profile file:

  1. Run webpack with ProfilingPlugin.
  2. Go to Chrome, open DevTools, and go to the Performance tab (formerly Timeline).
  3. Drag and drop generated file (events.json by default) into the profiler.

It will then display timeline stats and calls per plugin!

ProgressPlugin

The ProgressPlugin provides a way to customize how progress is reported during a compilation.

Usage

Create an instance of ProgressPlugin and provide one of the allowed params.

Providing 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 compilation
  • message: a short description of the currently-executing hook
  • ...args: zero or more additional strings describing the current progress
const handler = (percentage, message, ...args) => {
  // e.g. Output each progress message directly to the console:
  console.info(percentage, message, ...args);
};

new webpack.ProgressPlugin(handler);

Providing 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,
});

Percentage calculation

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.

Supported Hooks

The following hooks report progress information to ProgressPlugin.

Compiler

  • compilation
  • emit*
  • afterEmit*
  • done

Compilation

  • buildModule
  • failedModule
  • succeedModule
  • finishModules*
  • seal*
  • optimizeDependenciesBasic*
  • optimizeDependencies*
  • optimizeDependenciesAdvanced*
  • afterOptimizeDependencies*
  • optimize*
  • optimizeModulesBasic*
  • optimizeModules*
  • optimizeModulesAdvanced*
  • afterOptimizeModules*
  • optimizeChunksBasic*
  • optimizeChunks*
  • optimizeChunksAdvanced*
  • afterOptimizeChunks*
  • optimizeTree*
  • afterOptimizeTree*
  • optimizeChunkModulesBasic*
  • optimizeChunkModules*
  • optimizeChunkModulesAdvanced*
  • afterOptimizeChunkModules*
  • reviveModules*
  • optimizeModuleOrder*
  • advancedOptimizeModuleOrder*
  • beforeModuleIds*
  • moduleIds*
  • optimizeModuleIds*
  • afterOptimizeModuleIds*
  • reviveChunks*
  • optimizeChunkOrder*
  • beforeChunkIds*
  • optimizeChunkIds*
  • afterOptimizeChunkIds*
  • recordModules*
  • recordChunks*
  • beforeHash*
  • afterHash*
  • recordHash*
  • beforeModuleAssets*
  • beforeChunkAssets*
  • additionalChunkAssets*
  • record*
  • additionalAssets*
  • optimizeChunkAssets*
  • afterOptimizeChunkAssets*
  • optimizeAssets*
  • afterOptimizeAssets*
  • afterSeal*

Source

ProvidePlugin

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.

Usage: jQuery

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"

Usage: jQuery with Angular 1

Angular looks for window.jQuery in order to determine whether jQuery is present, see the source code.

new webpack.ProvidePlugin({
  'window.jQuery': 'jquery',
});

Usage: Lodash Map

new webpack.ProvidePlugin({
  _map: ['lodash', 'map'],
});

Usage: Vue.js

new webpack.ProvidePlugin({
  Vue: ['vue/dist/vue.esm.js', 'default'],
});

SourceMapDevToolPlugin

本插件实现了对 source map 生成内容进行更细粒度的控制。它也可以根据 devtool 配置选项的某些设置来自动启用。

new webpack.SourceMapDevToolPlugin(options);

配置项

支持以下配置项:

  • teststring RegExp [string, RegExp]):包含基于扩展名的模块的 source map(默认是 .js, .mjs.css)。
  • includestring RegExp [string, RegExp]):使路径与该值匹配的模块生成 source map。
  • excludestring RegExp [string, RegExp]):使匹配该值的模块不生成 source map。
  • filenamestring):定义生成的 SourceMap 的名称(不设置将默认置为 inlined)。
  • appendstring):在原始资源后追加给定值。通常是 #sourceMappingURL 注释。[url] 被替换成 source map 文件的 URL。webpack v4.36.0 之后支持 path 参数:[chunk][filename][contenthash]。设置 appendfalse 会禁止追加。
  • moduleFilenameTemplatestring):查看 output.devtoolModuleFilenameTemplate
  • fallbackModuleFilenameTemplatestring):查看上面的链接。
  • namespacestring):查看 output.devtoolNamespace
  • module = trueboolean):表示 loader 是否生成 source map。
  • columns = trueboolean):表示是否应该使用 column mapping。
  • noSources = falseboolean):防止源文件的内容被包含在 source map 中。
  • publicPath (string):生成带 public path 前缀的绝对 URL,例如:https://example.com/project/
  • fileContext (string):使得 [file] 参数作为本目录的相对路径。
  • sourceRootstring):给 SourceMap 中的 sourceRoot 属性提供一个自定义值。

fileContext 配置在你想要将 source map 存储到上层目录,以避免 ../../ 出现在绝对路径 [url] 里面时是有用的。

示例

下面的示例展示了本插件的一些常见用例。

基本使用

你可以使用以下代码将配置项 devtool: inline-source-map 替换为等效的自定义插件配置:

module.exports = {
  // ...
  devtool: false,
  plugins: [new webpack.SourceMapDevToolPlugin({})],
};

排除 Vendor Maps

以下代码会排除 vendor.js bundle 内模块的 source map。

new webpack.SourceMapDevToolPlugin({
  filename: '[name].js.map',
  exclude: ['vendor.js'],
});

在宿主环境外部化 source map

设置 source map 的 URL。在宿主环境需要授权的情况下很有用。

new webpack.SourceMapDevToolPlugin({
  append: '\n//# sourceMappingURL=https://example.com/sourcemap/[url]',
  filename: '[name].map',
});

还有一种场景,source map 存储在上层目录中时:

project
|- dist
  |- public
    |- bundle-[hash].js
  |- sourcemaps
    |- bundle-[hash].js.map

如下设置:

new webpack.SourceMapDevToolPlugin({
  filename: 'sourcemaps/[file].map',
  publicPath: 'https://example.com/project/',
  fileContext: 'public',
});

将会生成以下 URL:

https://example.com/project/sourcemaps/bundle-[hash].js.map

SplitChunksPlugin

最初,chunks(以及内部导入的模块)是通过内部 webpack 图谱中的父子关系关联的。CommonsChunkPlugin 曾被用来避免他们之间的重复依赖,但是不可能再做进一步的优化。

从 webpack v4 开始,移除了 CommonsChunkPlugin,取而代之的是 optimization.splitChunks

默认值

开箱即用的 SplitChunksPlugin 对于大部分用户来说非常友好。

默认情况下,它只会影响到按需加载的 chunks,因为修改 initial chunks 会影响到项目的 HTML 文件中的脚本标签。

webpack 将根据以下条件自动拆分 chunks:

  • 新的 chunk 可以被共享,或者模块来自于 node_modules 文件夹
  • 新的 chunk 体积大于 20kb(在进行 min+gz 之前的体积)
  • 当按需加载 chunks 时,并行请求的最大数量小于或等于 30
  • 当加载初始化页面时,并发请求的最大数量小于或等于 30

当尝试满足最后两个条件时,最好使用较大的 chunks。

配置

webpack 为希望对该功能进行更多控制的开发者提供了一组选项。

optimization.splitChunks

下面这个配置对象代表 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,
        },
      },
    },
  },
};

splitChunks.automaticNameDelimiter

string = '~'

默认情况下,webpack 将使用 chunk 的来源和名称生成名称(例如 vendors~main.js)。此选项使你可以指定用于生成名称的分隔符。

splitChunks.chunks

string = 'async' function (chunk)

这表明将选择哪些 chunk 进行优化。当提供一个字符串,有效值为 allasyncinitial。设置为 all 可能特别强大,因为这意味着 chunk 可以在异步和非异步 chunk 之间共享。

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',
    },
  },
};

或者,你也可以提供一个函数去做更多的控制。这个函数的返回值将决定是否包含每一个 chunk。

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks(chunk) {
        // exclude `my-excluded-chunk`
        return chunk.name !== 'my-excluded-chunk';
      },
    },
  },
};

splitChunks.maxAsyncRequests

number = 30

按需加载时的最大并行请求数。

splitChunks.maxInitialRequests

number = 30

入口点的最大并行请求数。

splitChunks.defaultSizeTypes

[string] = ['javascript', 'unknown']

Sets the size types which are used when a number is used for sizes.

splitChunks.minChunks

number = 1

拆分前必须共享模块的最小 chunks 数。

splitChunks.hidePathInfo

boolean

为由 maxSize 分割的部分创建名称时,阻止公开路径信息。

splitChunks.minSize

number = 20000 { [index: string]: number }

生成 chunk 的最小体积(以 bytes 为单位)。

splitChunks.minSizeReduction

number { [index: string]: number }

生成 chunk 所需的主 chunk(bundle)的最小体积(以字节为单位)缩减。这意味着如果分割成一个 chunk 并没有减少主 chunk(bundle)的给定字节数,它将不会被分割,即使它满足 splitChunks.minSize

splitChunks.enforceSizeThreshold

splitChunks.cacheGroups.{cacheGroup}.enforceSizeThreshold

number = 50000

强制执行拆分的体积阈值和其他限制(minRemainingSize,maxAsyncRequests,maxInitialRequests)将被忽略。

splitChunks.minRemainingSize

splitChunks.cacheGroups.{cacheGroup}.minRemainingSize

number = 0

在 webpack 5 中引入了 splitChunks.minRemainingSize 选项,通过确保拆分后剩余的最小 chunk 体积超过限制来避免大小为零的模块。 'development' 模式 中默认为 0。对于其他情况,splitChunks.minRemainingSize 默认为 splitChunks.minSize 的值,因此除需要深度控制的极少数情况外,不需要手动指定它。

splitChunks.layer

splitChunks.cacheGroups.{cacheGroup}.layer

RegExp string function

按模块层将模块分配给缓存组。

splitChunks.maxSize

number = 0

使用 maxSize(每个缓存组 optimization.splitChunks.cacheGroups[x].maxSize 全局使用 optimization.splitChunks.maxSize 或对后备缓存组 optimization.splitChunks.fallbackCacheGroup.maxSize 使用)告诉 webpack 尝试将大于 maxSize 个字节的 chunk 分割成较小的部分。 这些较小的部分在体积上至少为 minSize(仅次于 maxSize)。 该算法是确定性的,对模块的更改只会产生局部影响。这样,在使用长期缓存时就可以使用它并且不需要记录。maxSize 只是一个提示,当模块大于 maxSize 或者拆分不符合 minSize 时可能会被违反。

当 chunk 已经有一个名称时,每个部分将获得一个从该名称派生的新名称。 根据 optimization.splitChunks.hidePathInfo 的值,它将添加一个从第一个模块名称或其哈希值派生的密钥。

maxSize 选项旨在与 HTTP/2 和长期缓存一起使用。它增加了请求数量以实现更好的缓存。它还可以用于减小文件大小,以加快二次构建速度。

splitChunks.maxAsyncSize

number

maxSize 一样,maxAsyncSize 可以为 cacheGroups(splitChunks.cacheGroups.{cacheGroup}.maxAsyncSize)或 fallback 缓存组(splitChunks.fallbackCacheGroup.maxAsyncSize )全局应用(splitChunks.maxAsyncSize

maxAsyncSizemaxSize 的区别在于 maxAsyncSize 仅会影响按需加载 chunk。

splitChunks.maxInitialSize

number

maxSize 一样,maxInitialSize 可以对 cacheGroups(splitChunks.cacheGroups.{cacheGroup}.maxInitialSize)或 fallback 缓存组(splitChunks.fallbackCacheGroup.maxInitialSize)全局应用(splitChunks.maxInitialSize)。

maxInitialSizemaxSize 的区别在于 maxInitialSize 仅会影响初始加载 chunks。

splitChunks.name

boolean = false function (module, chunks, cacheGroupKey) => string string

每个 cacheGroup 也可以使用:splitChunks.cacheGroups.{cacheGroup}.name

拆分 chunk 的名称。设为 false 将保持 chunk 的相同名称,因此不会不必要地更改名称。这是生产环境下构建的建议值。

提供字符串或函数使你可以使用自定义名称。指定字符串或始终返回相同字符串的函数会将所有常见模块和 vendor 合并为一个 chunk。这可能会导致更大的初始下载量并减慢页面加载速度。

如果你选择指定一个函数,则可能会发现 chunk.namechunk.hash 属性(其中 chunkchunks 数组的一个元素)在选择 chunk 名时特别有用。

如果 splitChunks.nameentry point 名称匹配,entry point 将被删除。

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',
        },
      },
    },
  },
};

使用以下 splitChunks 配置来运行 webpack 也会输出一组公用组,其下一个名称为:commons-main-lodash.js.e7519d2bb8777058fa27.js(以哈希方式作为真实世界输出示例)。

splitChunks.usedExports

splitChunks.cacheGroups{cacheGroup}.usedExports

boolean = true

弄清哪些 export 被模块使用,以混淆 export 名称,省略未使用的 export,并生成有效的代码。 当它为 true 时:分析每个运行时使用的出口,当它为 "global" 时:分析所有运行时的全局 export 组合)。

splitChunks.cacheGroups

缓存组可以继承和/或覆盖来自 splitChunks.* 的任何选项。但是 testpriorityreuseExistingChunk 只能在缓存组级别上进行配置。将它们设置为 false以禁用任何默认缓存组。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        default: false,
      },
    },
  },
};

splitChunks.cacheGroups.{cacheGroup}.priority

number = -20

一个模块可以属于多个缓存组。优化将优先考虑具有更高 priority(优先级)的缓存组。默认组的优先级为负,以允许自定义组获得更高的优先级(自定义组的默认值为 0)。

splitChunks.cacheGroups.{cacheGroup}.reuseExistingChunk

boolean = true

如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块。这可能会影响 chunk 的结果文件名。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          reuseExistingChunk: true,
        },
      },
    },
  },
};

splitChunks.cacheGroups.{cacheGroup}.type

function RegExp string

允许按模块类型将模块分配给缓存组。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        json: {
          type: 'json',
        },
      },
    },
  },
};

splitChunks.cacheGroups.test

splitChunks.cacheGroups.{cacheGroup}.test

function (module, { chunkGraph, moduleGraph }) => boolean RegExp string

控制此缓存组选择的模块。省略它会选择所有模块。它可以匹配绝对模块资源路径或 chunk 名称。匹配 chunk 名称时,将选择 chunk 中的所有模块。

{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';
          },
        },
      },
    },
  },
};

为了查看 module and chunks 对象中可用的信息,你可以在回调函数中放入 debugger; 语句。然后 以调试模式运行 webpack 构建 检查 Chromium DevTools 中的参数。

{cacheGroup}.test 提供 RegExp

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

仅在初始 chunk 时才允许覆盖文件名。 也可以在 output.filename 中使用所有占位符。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          filename: '[name].bundle.js',
        },
      },
    },
  },
};

若为函数,则:

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`;
          },
        },
      },
    },
  },
};

通过提供以文件名开头的路径 'js/vendor/bundle.js',可以创建文件夹结构。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          filename: 'js/[name]/bundle.js',
        },
      },
    },
  },
};

splitChunks.cacheGroups.{cacheGroup}.enforce

boolean = false

告诉 webpack 忽略 splitChunks.minSizesplitChunks.minChunkssplitChunks.maxAsyncRequestssplitChunks.maxInitialRequests 选项,并始终为此缓存组创建 chunk。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          enforce: true,
        },
      },
    },
  },
};

splitChunks.cacheGroups.{cacheGroup}.idHint

string

设置 chunk id 的提示。 它将被添加到 chunk 的文件名中。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          idHint: 'vendors',
        },
      },
    },
  },
};

Examples

Defaults: Example 1

// index.js

import('./a'); // dynamic import
// a.js
import 'react';

//...

结果: 将创建一个单独的包含 react 的 chunk。在导入调用中,此 chunk 并行加载到包含 ./a 的原始 chunk 中。

为什么:

  • 条件1:chunk 包含来自 node_modules 的模块
  • 条件2:react 大于 30kb
  • 条件3:导入调用中的并行请求数为 2
  • 条件4:在初始页面加载时不影响请求

这背后的原因是什么?react 可能不会像你的应用程序代码那样频繁地更改。通过将其移动到单独的 chunk 中,可以将该 chunk 与应用程序代码分开进行缓存(假设你使用的是 chunkhash,records,Cache-Control 或其他长期缓存方法)。

Defaults: Example 2

// 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

//...

结果: 将创建一个单独的 chunk,其中包含 ./helpers 及其所有依赖项。在导入调用时,此 chunk 与原始 chunks 并行加载。

为什么:

  • 条件1:chunk 在两个导入调用之间共享
  • 条件2:helpers 大于 30kb
  • 条件3:导入调用中的并行请求数为 2
  • 条件4:在初始页面加载时不影响请求

helpers 的内容放入每个 chunk 中将导致其代码被下载两次。通过使用单独的块,这只会发生一次。我们会进行额外的请求,这可以视为一种折衷。这就是为什么最小体积为 30kb 的原因。

Split Chunks: Example 1

创建一个 commons chunk,其中包括入口(entry points)之间所有共享的代码。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          name: 'commons',
          chunks: 'initial',
          minChunks: 2,
        },
      },
    },
  },
};

Split Chunks: Example 2

创建一个 vendors chunk,其中包括整个应用程序中 node_modules 的所有代码。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      },
    },
  },
};

Split Chunks: Example 3

创建一个 custom vendor chunk,其中包含与 RegExp 匹配的某些 node_modules 包。

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
          name: 'vendor',
          chunks: 'all',
        },
      },
    },
  },
};

StylelintWebpackPlugin

npm node deps tests coverage chat size

stylelint-webpack-plugin 3.0 仅支持 webpack 5。对于 webpack 4,请查看 2.x 分支

该插件使用 stylelint 帮助你在样式代码中避免错误并强制规范。

Getting Started

首先,你需要安装 stylelint-webpack-plugin

npm install stylelint-webpack-plugin --save-dev

注意:如果你还没有安装 stylelint >= 13,请先用 npm 进行安装:

npm install stylelint --save-dev

然后添加该插件到你的 webpack 配置中。例如:

const StylelintPlugin = require('stylelint-webpack-plugin');

module.exports = {
  // ...
  plugins: [new StylelintPlugin(options)],
  // ...
};

选项

有关可用选项的完整列表请参阅 styleint 的配置项,这些选项直接传递给 stylelint

configFile

  • 类型:String
  • 默认值:undefined

指定 stylelint 配置文件的位置。

注意: 默认情况下由 stylelint 处理

context

  • 类型:String
  • 默认值:compiler.context

指定文件根目录的字符串。

exclude

  • 类型:String|Array[String]
  • 默认值:['node_modules', compiler.options.output.path]

指定要忽略的文件或目录。必须相对于 options.context

extensions

  • 类型:String|Array[String]
  • 默认值:['css', 'scss', 'sass']

指定要检查的扩展名。

files

  • 类型:String|Array[String]
  • 默认值:'**/*.(s(c|a)ss|css)'

可指定为目录,文件名或 globs。目录会递归地寻找与 options.extensions 相匹配的文件。文件名和 glob 模式将忽略 options.extensions

fix

  • 类型:Boolean
  • 默认值:false

如果值为 truestylelint 将修复尽可能多的 error。修复真实的源文件。报告所有未修复的 errors。请参阅 自动修复错误 文档。

formatter

  • 类型:String|Function
  • 默认值:'string'

指定要用于格式化结果的 formatter。请参阅 formatter 选项

lintDirtyModulesOnly

  • 类型:Boolean
  • 默认值:false

仅检查有变化的文件,启动时跳过检查。

stylelintPath

  • 类型:String
  • 默认值:stylelint

将要用来做检查的 stylelint 实例的路径。

threads

  • 类型:Boolean | Number
  • 默认值:false

设置为 true 时,会根据 cpu 的数量自动决定池子的大小。设置为大于 1 的数字时,可以确定池子的大小。设置为 false、1 或更小时,会禁用池子,并只在主线程运行。

Errors 和 Warning

默认情况下,插件将根据 stylelint 错误/警告数量自动调整错误报告。 你仍然可以使用 emitError emitWarning 选项来强制改变这种默认行为。

emitError

  • 类型:Boolean
  • 默认值:true

如遇到错误将会被直接输出,如需禁用,请设置为 false

emitWarning

  • 类型:Boolean
  • 默认值:true

如遇到警告将会被直接输出,如需禁用,请设置为 false

failOnError

  • 类型:Boolean
  • 默认值:true

如果有任何错误,都将导致模块构建失败,如需禁用,请设置为 false

failOnWarning

  • 类型:Boolean
  • 默认值:false

如果设置为 true,出现任何 warnings 都将会导致模块构建失败。

quiet

  • 类型:Boolean
  • 默认值:false

如果设置为 true,则仅处理和报告 errors,并忽略 warnings。

outputReport

  • 类型:Boolean|Object
  • 默认值:false

将输出的错误写入文件,例如,用于上报的 json 文件。 其 filePath 会相对于 webpack 配置中的:output.path. 你可以为输出文件设置不同的 formatter,如果未设置,则将使用默认 formatter

{
  'path/to/file';
  'json';
}

Changelog

Changelog

License

MIT

TerserWebpackPlugin

免责声明:TerserWebpackPlugin 是由社区成员维护的第三方包,它可能没有与 webpack 相同的支持、安全策略或许可证,并且它不是由 webpack 维护的。

npm node tests cover chat size

该插件使用 terser 来压缩 JavaScript。

入门

webpack v5 开箱即带有最新版本的 terser-webpack-plugin。如果你使用的是 webpack v5 或更高版本,同时希望自定义配置,那么仍需要安装 terser-webpack-plugin。如果使用 webpack v4,则必须安装 terser-webpack-plugin v4 的版本。

首先需要安装 terser-webpack-plugin

npm install terser-webpack-plugin --save-dev

然后将插件添加到 webpack 配置文件中,例如:

webpack.config.js

const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
  },
};

接下来,按照你习惯的方式运行 webpack

关于 source map 的说明

只对 devtool 选项的 source-mapinline-source-maphidden-source-mapnosources-source-map 有效

为何如此?

  • eval 通过 eval("string") 包裹模块而压缩工具不会处理字符串。
  • cheap 不存在列信息而压缩工具输出的文件为单行文件,只会留下一个映射。

使用支持的 devtool 值可以生成 source map。

选项

test

类型: String|RegExp|Array<String|RegExp> 默认值:/\.m?js(\?.*)?$/i

用来匹配需要压缩的文件。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        test: /\.js(\?.*)?$/i,
      }),
    ],
  },
};

include

类型: String|RegExp|Array<String|RegExp> 默认值: undefined

匹配参与压缩的文件。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        include: /\/includes/,
      }),
    ],
  },
};

exclude

类型: String|RegExp|Array<String|RegExp> 默认值: undefined

匹配不需要压缩的文件。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        exclude: /\/excludes/,
      }),
    ],
  },
};

parallel

类型: Boolean|Number 默认值: true

使用多进程并发运行以提高构建速度。 并发运行的默认数量: os.cpus().length - 1

并发运行可以显著提高构建速度,因此强烈建议添加此配置

如果你使用 Circle CI 或任何其他不提供 CPU 实际可用数量的环境,则需要显式设置 CPU 数量,以避免 Error: Call retries were exceeded(请参阅 #143#202 )。

Boolean

启用/禁用多进程并发运行功能。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: true,
      }),
    ],
  },
};

Number

启用多进程并发运行并设置并发运行次数。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: 4,
      }),
    ],
  },
};

minify

类型: Function 默认值: TerserPlugin.terserMinify

允许你自定义压缩函数。 默认情况下,插件使用 terser 库。 对于使用和测试未发布的版本或 fork 的代码很帮助。

⚠️ 启用 parallel 选项时,在 minify 函数内部只能使用 require

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

类型: Object 默认值: 默认

Terser 配置项

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

类型: Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>|Object 默认值: true

是否将注释剥离到单独的文件中(请参阅详细信息)。 默认情况下,仅剥离 /^\**!|@preserve|@license|@cc_on/i 正则表达式匹配的注释,其余注释会删除。 如果原始文件名为 foo.js ,则注释将存储到 foo.js.LICENSE.txtterserOptions.format.comments 选项指定是否保留注释,即可以在剥离其他注释时保留一些注释,甚至保留已剥离的注释。

Boolean

启用/禁用剥离注释功能。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: true,
      }),
    ],
  },
};

String

剥离 allsome (使用 /^\**!|@preserve|@license|@cc_on/i 正则表达式进行匹配)注释。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: 'all',
      }),
    ],
  },
};

RegExp

与指定表达式匹配的所有注释将会被剥离到单独的文件中。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: /@extract/i,
      }),
    ],
  },
};

Function<(node, comment) -> Boolean>

与指定表达式匹配的所有注释将会被剥离到单独的文件中。

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

允许自定义剥离注释的条件,指定剥离的文件名和标题。

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

类型: Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>

自定义需要剥离的注释。

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

类型: String|Function<(string) -> String> 默认值: [file].LICENSE.txt [query]

可用的占位符: [file][query][filebase] (webpack 5 使用 [base] )。

剥离出来的注释将被存储到的文件的文件名。 默认是将后缀 .LICENSE.txt 附加到原始文件名。

⚠️ 我们强烈建议使用 txt 扩展名。 使用 js / cjs / mjs 扩展名可能会与现有资源文件冲突,从而导致代码运行出错。

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

类型: Boolean|String|Function<(string) -> String> 默认值: /*! For license information please see ${commentsFile} */

指向剥离文件的标语文本将被添加到原始文件的顶部。 可以为 false (无标题), String 或一个函数:Function<(string) -> String> ,该函数将被使用存储剥离的注释的文件名来调用。 标语内容将被合并到注释中。

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}`;
          },
        },
      }),
    ],
  },
};

示例

保留注释

剥离所有有效的注释(即 /^\**!|@preserve|@license|@cc_on/i )并保留 /@license/i 注释。

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          format: {
            comments: /@license/i,
          },
        },
        extractComments: true,
      }),
    ],
  },
};

删除注释

如果要在构建时去除注释,请使用以下配置:

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          format: {
            comments: false,
          },
        },
        extractComments: false,
      }),
    ],
  },
};

uglify-js

UglifyJS 是一款集 JavaScript 解析器,压缩器,美化器于一身的工具集。

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 是一款采用 rust 编写的超快编译器;可以将最新标准和 TypeScript 的语法生成被广泛使用的 JavaScript。

extractComments 选项暂不支持,所有注释将默认被删除,会在将来得到修复。

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 是一款非常快速的 JavaScript 打包工具和压缩工具。

⚠ 不支持 extractComments 选项,所有法律相关的注释(如版权,许可证等)将被保留。

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: {},
      }),
    ],
  },
};

自定义压缩函数

覆盖默认的 minify 函数 - 使用 uglify-js 进行压缩。

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);
        },
      }),
    ],
  },
};

Typescript

使用默认 terser 压缩函数:

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: true,
        },
      }),
    ],
  },
};

使用内置压缩函数:

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
        },
      }),
    ],
  },
};

Contributing

请花一点时间阅读我们的贡献指南。

CONTRIBUTING

许可证

MIT

WatchIgnorePlugin

Ignore the specified files, i.e. those matching the provided paths or regular expressions, while in watch mode.

new webpack.WatchIgnorePlugin({ paths });

Options

  • paths (Array<string | RegExp>): A list of RegExps or absolute paths to directories or files that should be ignored.

1 位贡献者

webpack