Printable

AutomaticPrefetchPlugin

AutomaticPrefetchPlugin은 변경사항을 관찰하는 동안 이전 컴파일의 모든 모듈을 미리 검색하여 증가하는 빌드 시간을 개선합니다. 단일 모듈을 미리 검색하는 PrefetchPlugin 과 비교해보세요.

webpack.config.js

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

BannerPlugin

생성된 각 청크의 상단에 배너를 추가합니다.

const webpack = require('webpack');

new webpack.BannerPlugin(banner);
// 또는
new webpack.BannerPlugin(options);

Options

{
  banner: string | function, // 배너를 문자열 또는 함수로 사용하면, 주석으로 감싸집니다.
  raw: boolean, // true이면, 배너가 주석에 감싸지지 않습니다.
  entryOnly: boolean, // true이면, 배너는 엔트리 청크에만 추가됩니다.
  test: string | RegExp | [string, RegExp], // 테스트를 통과하는 모든 모듈이 포함됩니다.
  include: string | RegExp | [string, RegExp], // 다음 조건 중 하나라도 일치하는 모든 모듈이 포함됩니다.
  exclude: string | RegExp | [string, RegExp], // 다음 조건 중 하나라도 일치하는 모든 모듈이 제외됩니다.
  footer?: boolean, // true이면, 배너는 컴파일이 끝날 때 배치됩니다.
  stage?: number, // 배너를 주입해야 하는 컴파일 단계
}

Usage

import webpack from 'webpack';

// 문자열
new webpack.BannerPlugin({
  banner: 'hello world',
});

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

// 최소화 및 애셋 조작 후 배너 메시지를 추가합니다.
new webpack.BannerPlugin({
  raw: true,
  banner: '/* 배너는 문자열입니다 */',
  stage: webpack.Compilation.PROCESS_ASSETS_STAGE_REPORT,
});

Placeholders

webpack 2.5.0 부터, placeholder는 배너 문자열로 평가됩니다.

import webpack from 'webpack';

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

ChunksWebpackPlugin

GitHub Workflow Status (branch) Coverage Status Npm downloads

The chunks-webpack-plugin creates HTML files with entry points and chunks relations to serve your webpack bundles. It is suitable with multi-page applications that contain multiple entry points.

Since webpack 4, SplitChunksPlugin offers the possibility to optimizes all chunks. It can be particularly powerful, because it means that chunks can be shared even between async and non-async chunks. See the webpack documentation of splitChunks.chunks for details.

splitChunks.chunks option can be set to automatically generate new chunks associated with an entry point. For example, entry points a.js and b.js share common code with the file vendors~a~b.js.

With multiple entry points, it can be difficult to identify relation between the auto-generated chunks and entry points.

chunks-webpack-plugin parses the webpack compilation entry points to get all files associated with the entry points. Then, it generates HTML files which include all assets filtered by an entry point and thechunks-manifest.json file.

Zero configuration

It works without configuration. For advanced usage, see the using configuration section.

Installation

chunks-webpack-plugin is available on npm as chunks-webpack-plugin and as chunks-webpack-plugin on GitHub.

npm install chunks-webpack-plugin --save-dev
yarn add chunks-webpack-plugin --dev

Warning chunks-webpack-plugin@10 is ESM only.

Note Minimum supported Node.js version is 16.20.0 and Webpack >=5.10.3.

Example

The project includes a minimalist example in the ./example directory. Run the npm run build:example command to execute the Webpack example and see the plugin's implementation in action.

Basic usage

chunks-webpack-plugin will generate two HTML files for each entry point. Each filename contains the entry point name, the {{entry}} placeholder is automatically replaced.

  • {{entry}}-styles.html: contains all HTML <link> tags
  • {{entry}}-scripts.html: contains all HTML <script> tags

First, let's add the plugin to the webpack configuration.

webpack.config.js

import ChunksWebpackPlugin from 'chunks-webpack-plugin';

export default {
  plugins: [new ChunksWebpackPlugin()]
};

HTML files are built in the output path directory with the rest of the webpack compilation.

Now you can include the generated HTML files into your HTML page templates. You can do it with e.g. Twig.

main-styles.html

<link rel="stylesheet" href="main.css" />

main-scripts.html

<script defer src="main.js"></script>

Using a configuration

You can pass a configuration object to chunks-webpack-plugin to override the default settings.

filename

Type:

type filename = string;

Default: '[name]-[type].html'

Tells the plugin whether to personalize the filename of the generated files. Files are processed by the webpack compilation and generated in the output path directory. The placeholder [name] is automatically replaced by entry points names and [type] by styles|scripts.

new ChunksWebpackPlugin({
  filename: 'templates/[name]-[type].html'
});

Note The filename can contain directories, which will be created automatically.

templateStyle

Type:

type templateStyle = (name: string, entryName: string) => string;

Default:

(name) => `<link rel="stylesheet" href="${name}" />`;

Tells the plugin whether to personalize the default template for the HTML <style> tags. For example, add additional attributes or a CDN prefix.

export default {
  plugins: [
    new ChunksWebpackPlugin({
      templateStyle: (name) => `<link rel="stylesheet" href="https://cdn.domain.com${name}" />`
    })
  ]
};

templateScript

Type:

type templateScript = (name: string, entryName: string) => string;

Default:

(name) => `<script defer src="${name}"></script>`;

Tells the plugin whether to personalize the default template for the HTML <script> tags. For example, add additional attributes or a CDN prefix.

export default {
  plugins: [
    new ChunksWebpackPlugin({
      templateScript: (name) => `<script defer src="https://cdn.domain.com${name}"></script>`
    })
  ]
};

generateChunksManifest

Type:

type generateChunksManifest = boolean;

Default: false

Tells the plugin whether to generate the chunks-manifest.json. The file contains the list of all chunks grouped by entry points. See the chunks-manifest.json example.

export default {
  plugins: [
    new ChunksWebpackPlugin({
      generateChunksManifest: true
    })
  ]
};

generateChunksFiles

Type:

type generateChunksFiles = boolean;

Default: true

Tells the plugin whether to generate the HTML files.

export default {
  plugins: [
    new ChunksWebpackPlugin({
      generateChunksFiles: false
    })
  ]
};

Warning When set to false, HTML files will not be generated. It can only be useful together with generateChunksManifest option set to true for custom generation of the HTML files.


Multiple entrypoints example

Multiple entrypoints example

Example of the webpack configuration with multiple entry points which share common code with the splitChunks option.

import ChunksWebpackPlugin from 'chunks-webpack-plugin';
import path from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export default {
  entry: {
    home: 'home.js',
    news: 'news.js'
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist')
  },
  plugins: [new ChunksWebpackPlugin()],
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  }
};

The plugin will generate all files in the output path directory:

home-styles.html

<link rel="stylesheet" href="vendors~home~news.css" />
<link rel="stylesheet" href="home.css" />

home-scripts.html

<script defer src="vendors~home~news.js"></script>
<script defer src="home.js"></script>

news-styles.html

<link rel="stylesheet" href="vendors~home~news.css" />
<link rel="stylesheet" href="news.css" />

news-scripts.html

<script defer src="vendors~home~news.js"></script>
<script defer src="news.js"></script>

License

chunks-webpack-plugin is licensed under the MIT License.

Created with ♥ by @yoriiis.

CommonsChunkPlugin

CommonsChunkPlugin은 여러 엔트리 포인트 간에 공유되는 공통 모듈로 이루어진 별도의 파일(청크라고 합니다)을 만드는 opt-in 기능입니다.

번들에서 공통 모듈을 분리한 결과로 생성된 청크 파일을 처음에 한 번 로드하고 나중에 사용하기 위해 캐시에 저장할 수 있습니다. 이로 인해 브라우저가 새 페이지를 방문할 때마다 더 큰 번들을 로드하지 않고 캐시에서 공유 코드를 빠르게 제공할 수 있으므로 페이지 속도가 최적화됩니다.

new webpack.optimize.CommonsChunkPlugin(options);

Options

{
  name: string, // 또는
  names: string[],
  // 공통 청크의 청크 이름입니다. 청크의 이름을 전달하여 기존 청크를 선택할 수 있습니다.
  // 문자열 배열로 전달되면 각 청크 이름에 대해 플러그인을 여러 번 호출하는 것과 같습니다.
  // 생략하면 `options.async` 또는 `options.children`이 설정되고 모든 청크가 사용됩니다.
  // 그렇지 않으면 청크 이름으로 사용되는 `options.filename`이 사용되게 됩니다.
  // `options.async`를 사용하여 다른 비동기 청크에서 공통 청크를 만들 때 `option.name`을 생략하는 대신 여기에
  // 엔트리 포인트 청크 이름을 지정해야 합니다.

  filename: string,
  // 공통 청크의 파일 이름 템플릿입니다. `output.filename`과 동일한 플레이스홀더를 포함할 수 있습니다.
  // 생략하면 원본 파일 이름은 수정되지 않습니다(일반적으로 `output.filename` 혹은 `output.chunkFilename`).
  // 이 옵션은 `options.async`를 사용하는 경우에도 허용되지 않습니다. 자세한 내용은 아래를 참조하세요.

  minChunks: number|Infinity|function(module, count) => boolean,
  // 공통 청크로 이동하기 전에 모듈을 포함해야 하는 최소 청크 수입니다.
  // 숫자는 2보다 크거나 같고 청크 수보다 작거나 같아야 합니다.
  // `Infinity`를 전달하면 공통 청크가 생성되지만 모듈은 이동하지 않습니다.
  // `function`을 제공하여 맞춤 로직을 추가 할 수 있습니다.(기본값은 청크의 수입니다)

  chunks: string[],
  // 청크 이름으로 소스 청크를 선택합니다. 청크는 공통 청크의 자식이어야 합니다.
  // 생략하면 모든 엔트리 청크가 선택됩니다.

  children: boolean,
  // `true`이면 공통 청크의 모든 자식이 선택됩니다.

  deepChildren: boolean,
  // `true`이면 공통 청크의 모든 자손이 선택됩니다.

  async: boolean|string,
  // `true`이면 새로운 비동기 공통 청크가 `options.name`의 하위 항목 및 `options.chunks`와 동등한 항목으로 생성됩니다.
  // `options.chunks`와 병렬로 로드됩니다.
  // `option.filename`을 사용하는 대신 `true`가 아닌 원하는 문자열을 제공해
  // 출력 파일의 이름을 변경할 수 있습니다.

  minSize: number,
  // 공통 청크가 생성되기 전 모든 공통 모듈의 최소 사이즈입니다.
}

Examples

Commons chunk for entries

엔트리 포인트 간에 공유되는 공통 모듈을 포함하는 추가 청크를 생성합니다.

new webpack.optimize.CommonsChunkPlugin({
  name: 'commons',
  // (공통 청크 이름)

  filename: 'commons.js',
  // (공통 청크의 파일 이름)

  // minChunks: 3,
  // (모듈은 최소 3개의 엔트리 사이에서 공유해야 합니다)

  // chunks: ["pageA", "pageB"],
  // (이 엔트리에서만 사용됩니다)
});

생성된 청크는 엔트리 포인트 전에 로드해야 합니다.

<script src="commons.js" charset="utf-8"></script>
<script src="entry.bundle.js" charset="utf-8"></script>

Explicit vendor chunk

코드를 vendor와 애플리케이션으로 분할합니다.

module.exports = {
  //...
  entry: {
    vendor: ['jquery', 'other-lib'],
    app: './entry',
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      // filename: "vendor.js"
      // (청크에 다른 이름을 지정하세요)

      minChunks: Infinity,
      // (엔트리가 더 많으면 다른 모듈이 vendor 청크로
      //  들어가지 않습니다)
    }),
  ],
};
<script src="vendor.js" charset="utf-8"></script>
<script src="app.js" charset="utf-8"></script>

Move common modules into the parent chunk

Code Splitting을 사용하면 엔트리 청크의 여러 하위(자식) 청크가 공통 종속성을 가질 수 있습니다. 중복을 방지하기 위해 이들을 부모 청크로 옮길 수 있습니다. 이렇게 하면 전체 크기가 줄어들지만, 초기 로드 시간에 부정적인 영향을 미칩니다. 사용자가 많은 형제 청크(예: 엔트리 청크의 자식)를 다운로드해야 할 것으로 예상되는 경우 전체 로드 시간이 향상됩니다.

new webpack.optimize.CommonsChunkPlugin({
  // names: ["app", "subPageA"]
  // (청크를 선택하거나 모든 청크를 생략하세요)

  children: true,
  // (선택된 청크의 모든 자식을 선택합니다)

  // minChunks: 3,
  // (모듈을 옮기기 전에 3명의 자식이 공유해야 합니다)
});

Extra async commons chunk

위의 것과 유사하지만 공통 모듈을 부모로 이동하는 대신(초기 로드 시간을 증가시키게 됩니다) 비동기식으로 로드된 새로운 추가 공통 청크가 사용됩니다. 이는 추가 청크가 다운로드되면 자동으로 병렬로 다운로드됩니다.

new webpack.optimize.CommonsChunkPlugin({
  name: 'app',
  // 또는
  names: ['app', 'subPageA'],
  // 단일 이름 또는 배열 형태의 이름은 비동기 청크를 생성하는
  // 엔트리 포인트의 이름과 일치해야 합니다.

  children: true,
  // (청크의 모든 자식을 사용합니다)

  async: true,
  // (비동기 공통 청크를 생성합니다)

  minChunks: 3,
  // (모듈이 분리되기 전에 3명의 자식이 모듈을 공유해야 합니다)
});

Passing the minChunks property a function

또한 minChunks 속성에 함수를 전달할 수도 있습니다. 이 함수는 CommonsChunkPlugin에 의해 호출되며 modulecount 인수로 함수를 호출합니다.

module 인수는 name/names 속성을 통해 제공된 청크의 각 모듈을 나타냅니다. moduleNormalModule의 형태로, 이 사용 사례에 특히 유용한 두 개의 속성이 있습니다.

  • module.context: 파일을 저장하는 디렉터리입니다. 예: '/my_project/node_modules/example-dependency'
  • module.resource: 처리중인 파일의 이름입니다. 예: '/my_project/node_modules/example-dependency/index.js'

count 인수는 module이 사용되는 청크 수를 나타냅니다.

이 옵션은 CommonsChunk 알고리즘을 통해 모듈을 이동할 위치를 결정하는 방법을 세밀하게 제어하려는 경우에 유용합니다.

new webpack.optimize.CommonsChunkPlugin({
  name: 'my-single-lib-chunk',
  filename: 'my-single-lib-chunk.js',
  minChunks: function (module, count) {
    // 모듈이 경로를 가지고 있고 경로에 "somelib"이 존재하고
    // 3개의 개별 청크/엔트리에서 사용되는 경우
    // 청크의 키 이름이 "my-single-lib-chunk", 파일 이름이 "my-single-lib-chunk.js"로 분할됩니다.
    return module.resource && /somelib/.test(module.resource) && count === 3;
  },
});

위에서 볼 수 있듯이 이 예제를 사용하면 함수 내의 모든 조건이 충족되는 경우에만, 하나의 라이브러리를 별도의 파일로 이동할 수 있습니다.

이 개념은 암시적 공통 vendor 청크를 얻는데 사용할 수 있습니다.

new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: function (module) {
    // 이는 vendor의 import가 node_modules 디렉터리에 존재한다고 가정합니다.
    return module.context && module.context.includes('node_modules');
  },
});

Manifest file

webpack 부트스트랩 로직을 별도의 파일로 추출하려면 entry로 정의되어 있지 않은 nameCommonsChunkPlugin을 사용하세요. 자세한 내용은 캐싱 가이드를 참조하세요.

new webpack.optimize.CommonsChunkPlugin({
  name: 'manifest',
  minChunks: Infinity,
});

Combining implicit common vendor chunks and manifest file

vendormanifest 청크는 minChunks에 대해 다른 정의를 사용하므로 플러그인을 두 번 호출해야 합니다.

[
  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 tests cover discussion 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

or

yarn add -D compression-webpack-plugin

or

pnpm add -D compression-webpack-plugin

Then add the plugin to your webpack config. For example:

webpack.config.js

const CompressionPlugin = require("compression-webpack-plugin");

module.exports = {
  plugins: [new CompressionPlugin()],
};

And run webpack via your preferred method.

Options

test

Type:

type test = string | RegExp | Array<string | RegExp>;

Default: undefined

Include all assets that pass test assertion.

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      test: /\.js(\?.*)?$/i,
    }),
  ],
};

include

Type:

type include = string | RegExp | Array<string | RegExp>;

Default: undefined

Include all assets matching any of these conditions.

webpack.config.js

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

exclude

Type:

type exclude = string | RegExp | Array<string | RegExp>;

Default: undefined

Exclude all assets matching any of these conditions.

webpack.config.js

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

algorithm

Type:

type algorithm =
  | string
  | ((
      input: Buffer,
      options: CompressionOptions,
      callback: (
        error: Error | null | undefined,
        result:
          | string
          | ArrayBuffer
          | SharedArrayBuffer
          | Uint8Array
          | readonly number[]
          | {
              valueOf(): ArrayBuffer | SharedArrayBuffer;
            }
          | {
              valueOf(): string | Uint8Array | readonly number[];
            }
          | {
              valueOf(): string;
            }
          | {
              [Symbol.toPrimitive](hint:%20%22string%22): string;
            },
      ) => void,
    ) => any);

Default: gzip

The compression algorithm/function.

[!NOTE]

If you use custom function for the algorithm option, the default value of 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:

type compressionOptions = {
  flush?: number;
  finishFlush?: number;
  chunkSize?: number;
  windowBits?: number;
  level?: number;
  memLevel?: number;
  strategy?: number;
  dictionary?: Buffer | TypedArray | DataView | ArrayBuffer;
  info?: boolean;
  maxOutputLength?: number;
};

Default: { level: 9 }

Compression options for algorithm.

You can find all options here zlib.

[!NOTE]

If you use custom function for the algorithm option, the default value is {}.

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      compressionOptions: { level: 1 },
    }),
  ],
};

threshold

Type:

type threshold = number;

Default: 0

Only assets bigger than this size are processed. In bytes.

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      threshold: 8192,
    }),
  ],
};

minRatio

Type:

type minRatio = number;

Default: 0.8

Only assets that compress better than this ratio are processed (minRatio = Compressed Size / Original Size). Example: you have image.png file with 1024b size, compressed version of file has 768b size, so minRatio equal 0.75. In other words assets will be processed when the Compressed Size / Original Size value less minRatio value.

You can use 1 value to process assets that are smaller than the original.

Use a value of Infinity to process all assets even if they are larger than the original size or their original size is 0 bytes (useful when you are pre-zipping all assets for AWS).

Use a value of Number.MAX_SAFE_INTEGER to process all assets even if they are larger than the original size, excluding assets with their original size is 0 bytes.

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      // Compress all assets, including files with `0` bytes size
      // minRatio: Infinity

      // Compress all assets, excluding files with `0` bytes size
      // minRatio: Number.MAX_SAFE_INTEGER

      minRatio: 0.8,
    }),
  ],
};

filename

Type:

type filename = string | ((pathdata: PathData) => string);

Default: "[path][base].gz"

The target asset filename.

string

For example we have assets/images/image.png?foo=bar#hash:

[path] is replaced with the directories to the original asset, included trailing / (assets/images/).

[file] is replaced with the path of original asset (assets/images/image.png).

[base] is replaced with the base ([name] + [ext]) of the original asset (image.png).

[name] is replaced with the name of the original asset (image).

[ext] is replaced with the extension of the original asset, included . (.png).

[query] is replaced with the query of the original asset, included ? (?foo=bar).

[fragment] is replaced with the fragment (in the concept of URL it is called hash) of the original asset (#hash).

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      filename: "[path][base].gz",
    }),
  ],
};

function

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      filename(pathData) {
        // The `pathData` argument contains all placeholders - `path`/`name`/`ext`/etc
        // Available properties described above, for the `String` notation
        if (/\.svg$/.test(pathData.filename)) {
          return "assets/svg/[path][base].gz";
        }

        return "assets/js/[path][base].gz";
      },
    }),
  ],
};

deleteOriginalAssets

Type:

type deleteOriginalAssets =
  | boolean
  | "keep-source-map"
  | ((name: string) => boolean);

Default: false

Whether to delete the original assets or not.

webpack.config.js

module.exports = {
  plugins: [
    new CompressionPlugin({
      deleteOriginalAssets: true,
    }),
  ],
};

To exclude sourcemaps from compression:

module.exports = {
  plugins: [
    new CompressionPlugin({
      exclude: /.map$/,
      deleteOriginalAssets: "keep-source-map",
    }),
  ],
};

Using a custom function:

module.exports = {
  plugins: [
    new CompressionPlugin({
      exclude: /.map$/,
      deleteOriginalAssets: (name) => {
        if (/\.js$/.test(name)) {
          return false;
        }

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

Examples

Using Zopfli

Prepare compressed versions of assets using zopfli library.

[!NOTE]

@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

컨텍스트require('./locale/' + name + '.json')와 같은 표현식으로 구성된 요청을 의미합니다.

ContextExclusionPlugin을 사용하면 컨텍스트를 제외할 수 있습니다. 정규 표현식과 일치하는 모든 컨텍스트를 제외하려면 플러그인을 초기화할 때 정규 표현식을 인수로 제공하세요.

webpack.config.js

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

ContextReplacementPlugin

Context는 require('./locale/' + name + '.json')와 같은 표현식을 통한 요청을 나타냅니다. 이러한 표현식을 만나면, webpack은 디렉터리 ('./locale/')와 정규 표현식 (/^.*\.json$/)을 추론합니다. 컴파일 시 name을 알 수 없기 때문에 webpack은 모든 파일을 번들에 모듈로 포함합니다.

ContextReplacementPlugin을 사용하면 추론된 정보를 오버라이드 할 수 있습니다. 플러그인을 구성하는 방법에는 여러 가지가 있습니다.

Usage

new webpack.ContextReplacementPlugin(
  resourceRegExp: RegExp,
  newContentResource?: string,
  newContentRecursive?: boolean,
  newContentRegExp?: RegExp
)

리소스(디렉터리)가 resourceRegExp와 일치하면, 플러그인은 기본 리소스, 재귀 플래그 또는 생성된 정규식을 각각 newContentResource, newContentRecursive 또는 newContextRegExp로 바꿉니다. newContentResource가 상대적인 경우 이전 리소스를 기준으로 해결됩니다.

다음은 모듈 사용을 제한하는 작은 예제입니다.

new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /de|fr|hu/);

moment/locale 컨텍스트는 /de|fr|hu/와 일치하는 파일로 제한됩니다. 따라서 해당 locale만 포함됩니다(자세한 내용은 이 이슈를 참고하세요).

Content Callback

new webpack.ContextReplacementPlugin(
  resourceRegExp: RegExp,
  newContentCallback: (data) => void
);

newContentCallback 함수에는 ContextModuleFactorydata 객체가 제공되며 제공된 객체의 request 속성을 덮어쓸 것으로 예상됩니다.

이 콜백을 사용하여 요청을 새 위치로 동적 리다이렉션할 수 있습니다.

new webpack.ContextReplacementPlugin(/^\.\/locale$/, (context) => {
  if (!/\/moment\//.test(context.context)) return;

  Object.assign(context, {
    regExp: /^\.\/\w+/,
    request: '../../locale', // 상대적으로 해결
  });
});

Other Options

newContentResourcenewContentCreateContextMap 파라미터도 사용할 수 있습니다.

new webpack.ContextReplacementPlugin(
  resourceRegExp: RegExp,
  newContentResource: string,
  newContentCreateContextMap: object // 런타임-요청(userRequest)을 컴파일-시간-요청(request)으로 매핑
);

이 두 파라미터를 함께 사용하여 보다 대상화된 방식으로 요청을 리다이렉션할 수 있습니다. newContentCreateContextMap을 사용하면 런타임 요청을 매핑하여 객체 형태로 요청을 컴파일 할 수 있습니다.

new ContextReplacementPlugin(/selector/, './folder', {
  './request': './request',
  './other-request': './new-request',
});

CopyWebpackPlugin

npm node tests cover discussion 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

or

yarn add -D copy-webpack-plugin

or

pnpm add -D copy-webpack-plugin

Then add the plugin to your webpack config. For example:

webpack.config.js

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

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

[!NOTE]

copy-webpack-plugin is not designed to copy files generated from the build process; rather, it is to copy files that already exist in the source tree, as part of the build process.

[!NOTE]

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

[!NOTE]

You can get the original source filename from Asset Objects.

Options

The plugin's signature:

webpack.config.js

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

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        { from: "source", to: "dest" },
        "path/to/source", // absolute or relative, files/directories/globs - see below for examples
      ],
      options: {
        concurrency: 100,
      },
    }),
  ],
};

Patterns

from

Type:

type from = string;

Default: undefined

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

[!WARNING]

Don't use directly \\ 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:

type to =
  | string
  | ((pathData: { context: string; absoluteFilename?: string }) => string);

Default: compiler.options.output

string

Output path.

[!WARNING]

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.

[!WARNING]

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:

type context = string;

Default: options.context|compiler.options.context

A path to be (1) prepended to from and (2) removed from the start of the result path(s).

[!WARNING]

Don't use directly \\ 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/",
        },
      ],
    }),
  ],
};

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

context should be explicitly set only when from contains a glob. Otherwise, context is automatically set, based on whether from is a file or a directory:

If from is a file, then context is its directory. The result path will be the filename alone.

If from is a directory, then context equals from. The result paths will be the paths of the directory's contents (including nested contents), relative to the directory.

The use of context is illustrated by these examples.

globOptions

[!WARNING]

The onlyDirectories does not work because the plugin is designed to copy files.

Type:

type globOptions = import("globby").Options;

Default: undefined

Allows to configure the glob pattern matching library used by the plugin. See the list of supported options To exclude files from the selection, you should use globOptions.ignore option

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "public/**/*",
          globOptions: {
            dot: true,
            gitignore: true,
            ignore: ["**/file.*", "**/ignored-directory/**"],
          },
        },
      ],
    }),
  ],
};

filter

Type:

type filter = (filepath: string) => boolean;

Default: undefined

[!NOTE]

To ignore files by path please use the globOptions.ignore option.

webpack.config.js

const fs = require("fs").promise;

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "public/**/*",
          filter: async (resourcePath) => {
            const data = await fs.promises.readFile(resourcePath);
            const content = data.toString();

            if (content === "my-custom-content") {
              return false;
            }

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

toType

Type:

type toType = "dir" | "file" | "template";

Default: undefined

Determinate what is to option - directory, file or template. Sometimes it is hard to say what is to, example path/to/dir-with.ext. If you want to copy files in directory you need use dir option. We try to automatically determine the type so you most likely do not need this option.

NameTypeDefaultDescription
'dir'stringundefinedIf to has no extension or ends on '/'
'file'stringundefinedIf to is not a directory and is not a template
'template'stringundefinedIf to contains a template pattern
'dir'

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "path/to/file.txt",
          to: "directory/with/extension.ext",
          toType: "dir",
        },
      ],
    }),
  ],
};
'file'

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "path/to/file.txt",
          to: "file/without/extension",
          toType: "file",
        },
      ],
    }),
  ],
};
'template'

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/",
          to: "dest/[name].[contenthash][ext]",
          toType: "template",
        },
      ],
    }),
  ],
};

force

Type:

type force = boolean;

Default: false

Overwrites files already in compilation.assets (usually added by other plugins/loaders).

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/**/*",
          to: "dest/",
          force: true,
        },
      ],
    }),
  ],
};

priority

Type:

type priority = number;

Default: 0

Allows to specify the priority of copying files with the same destination name. Files for patterns with higher priority will be copied later. To overwrite files, the force option must be enabled.

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        // Copied second and will overwrite "dir_2/file.txt"
        {
          from: "dir_1/file.txt",
          to: "newfile.txt",
          force: true,
          priority: 10,
        },
        // Copied first
        {
          from: "dir_2/file.txt",
          to: "newfile.txt",
          priority: 5,
        },
      ],
    }),
  ],
};

transform

Type:

type transform =
  | {
      transformer: (input: string, absoluteFilename: string) => string | Buffer;
      cache?: boolean | TransformerCacheObject | undefined;
    }
  | ((input: string, absoluteFilename: string) => string | Buffer);

Default: undefined

Allows to modify the file contents.

function

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          // The `content` argument is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
          // The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied
          transform(content, absoluteFrom) {
            return optimize(content);
          },
        },
      ],
    }),
  ],
};
object
NameDefaultDescription
transformerundefinedAllows to modify the file contents.
cachefalseEnable transform caching. You can use transform: { cache: { key: 'my-cache-key' } } to invalidate the cache.
transformer

Type:

type transformer = (input: string, absoluteFilename: string) => string;

Default: undefined

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          // The `content` argument is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
          // The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied
          transform: {
            transformer(content, absoluteFrom) {
              return optimize(content);
            },
          },
        },
      ],
    }),
  ],
};

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          transform: {
            transformer(content, path) {
              return Promise.resolve(optimize(content));
            },
          },
        },
      ],
    }),
  ],
};
cache

Type:

type cache =
  | boolean
  | {
      keys: {
        [key: string]: any;
      };
    }
  | {
      keys: (
        defaultCacheKeys: {
          [key: string]: any;
        },
        absoluteFilename: string,
      ) => Promise<{
        [key: string]: any;
      }>;
    }
  | undefined;

Default: false

webpack.config.js

Enable/disable and configure caching. Default path to cache directory: node_modules/.cache/copy-webpack-plugin.

boolean

Enables/Disable transform caching.

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          transform: {
            transformer(content, path) {
              return optimize(content);
            },
            cache: true,
          },
        },
      ],
    }),
  ],
};
object

Enables transform caching and setup invalidation keys.

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          transform: {
            transformer(content, path) {
              return optimize(content);
            },
            cache: {
              keys: {
                // May be useful for invalidating cache based on external values
                // For example, you can invalid cache based on `process.version` - { node: process.version }
                key: "value",
              },
            },
          },
        },
      ],
    }),
  ],
};

You can setup invalidation keys using a function.

Simple function:

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          transform: {
            transformer(content, path) {
              return optimize(content);
            },
            cache: {
              keys: (defaultCacheKeys, absoluteFrom) => {
                const keys = getCustomCacheInvalidationKeysSync();

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

Async function:

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/*.png",
          to: "dest/",
          transform: {
            transformer(content, path) {
              return optimize(content);
            },
            cache: {
              keys: async (defaultCacheKeys, absoluteFrom) => {
                const keys = await getCustomCacheInvalidationKeysAsync();

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

transformAll

Type:

type transformAll = (
  data: {
    data: Buffer;
    sourceFilename: string;
    absoluteFilename: string;
  }[],
) => any;

Default: undefined

Allows you to modify the contents of multiple files and save the result to one file.

[!NOTE]

The to option must be specified and point to a file. It is allowed to use only [contenthash] and [fullhash] template strings.

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/**/*.txt",
          to: "dest/file.txt",
          // The `assets` argument is an assets array for the pattern.from ("src/**/*.txt")
          transformAll(assets) {
            const result = assets.reduce((accumulator, asset) => {
              // The asset content can be obtained from `asset.source` using `source` method.
              // The asset content is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
              const content = asset.data;

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

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

noErrorOnMissing

Type:

type noErrorOnMissing = boolean;

Default: false

Doesn't generate an error on missing file(s).

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, "missing-file.txt"),
          noErrorOnMissing: true,
        },
      ],
    }),
  ],
};

info

Type:

type info =
  | Record<string, any>
  | ((item: {
      absoluteFilename: string;
      sourceFilename: string;
      filename: string;
      toType: ToType;
    }) => Record<string, any>);

Default: undefined

Allows to add assets info.

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        "relative/path/to/file.ext",
        {
          from: "**/*",
          // Terser skip this file for minimization
          info: { minimized: true },
        },
      ],
    }),
  ],
};

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        "relative/path/to/file.ext",
        {
          from: "**/*",
          // Terser skip this file for minimization
          info: (file) => ({ minimized: true }),
        },
      ],
    }),
  ],
};

Options

concurrency

type:

type concurrency = number;

default: 100

limits the number of simultaneous requests to fs

webpack.config.js

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

Examples

Different variants of 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 don't want the result paths to start with src/directory-nested/, then you should move src/directory-nested/ to context, such that only the glob pattern **/* remains in from:

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "**/*",
          context: path.resolve(__dirname, "src", "directory-nested"),
        },
      ],
    }),
  ],
};

Result:

deep-nested/deepnested-file.txt,
nested-file.txt
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.

[!WARNING]

If files have the same name, the result is non-deterministic.

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "src/**/*",
          to: "[name][ext]",
        },
      ],
    }),
  ],
};

Result:

file-1.txt
file-2.txt
nested-file.txt

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

Useful if you need to simply copy *.js files to destination "as is" without evaluating and minimizing them using Terser.

webpack.config.js

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        "relative/path/to/file.ext",
        {
          from: "**/*",
          // Terser skip this file for minimization
          info: { minimized: true },
        },
      ],
    }),
  ],
};
yarn workspaces and monorepos

When using yarn workspaces or monorepos, relative copy paths from node_modules can be broken due to the way packages are hoisting. To avoid this, should explicitly specify where to copy the files from using require.resolve.

webpack.config.js

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

Contributing

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

CONTRIBUTING

License

MIT

CssMinimizerWebpackPlugin

npm node tests cover discussion size

This plugin uses cssnano to optimize and minify your CSS.

Just like optimize-css-assets-webpack-plugin but more accurate with source maps and assets using query string, allows caching and works in parallel mode.

Getting Started

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

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

or

yarn add -D css-minimizer-webpack-plugin

or

pnpm add -D css-minimizer-webpack-plugin

Then add the plugin to your webpack configuration. For example:

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      {
        test: /.s?css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
    ],
  },
  optimization: {
    minimizer: [
      // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
      // `...`,
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [new MiniCssExtractPlugin()],
};

This will enable CSS optimization only in production mode.

If you want to run it also in development set the optimization.minimize option to true:

webpack.config.js

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

And run webpack via your preferred method.

Note about source maps

Works only with source-map, inline-source-map, hidden-source-map and nosources-source-map values for the devtool option.

Why? Because CSS support only these source map types.

The plugin respect the devtool and using the SourceMapDevToolPlugin plugin. Using supported devtool values enable source map generation. Using SourceMapDevToolPlugin with enabled the columns option enables source map generation.

Use source maps to map error message locations to modules (this slows down the compilation). If you use your own minify function please read the minify section for handling source maps correctly.

Options

NameTypeDefaultDescription
testString|RegExp|Array<String|RegExp>/\.css(\?.*)?$/iTest to match files against.
includeString|RegExp|Array<String|RegExp>undefinedFiles to include.
excludeString|RegExp|Array<String|RegExp>undefinedFiles to exclude.
parallelBoolean|NumbertrueEnable/disable multi-process parallel running.
minifyFunction|Array<Function>CssMinimizerPlugin.cssnanoMinifyAllows to override default minify function.
minimizerOptionsObject|Array<Object>{ preset: 'default' }Cssnano optimisations options.
warningsFilterFunction<(warning, file, source) -> Boolean>() => trueAllow to filter css-minimizer warnings.

test

Type: String|RegExp|Array<String|RegExp> - default: /\.css(\?.*)?$/i

Test to match files against.

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

include

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

Files to include.

webpack.config.js

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

exclude

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

Files to exclude.

webpack.config.js

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

parallel

Type: Boolean|Number Default: true

Use multi-process parallel running to improve the build speed. Default number of concurrent runs: os.cpus().length - 1.

ℹ️ Parallelization can speed up your build significantly and is therefore highly recommended. If a parallelization is enabled, the packages in minimizerOptions must be required via strings (packageName or require.resolve(packageName)). Read more in minimizerOptions

Boolean

Enable/disable multi-process parallel running.

webpack.config.js

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

Number

Enable multi-process parallel running and set number of concurrent runs.

webpack.config.js

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

minify

Type: Function|Array<Function> Default: CssMinimizerPlugin.cssnanoMinify

Allows overriding default minify function. By default, plugin uses cssnano package. Useful for using and testing unpublished versions or forks.

Possible options:

  • CssMinimizerPlugin.cssnanoMinify
  • CssMinimizerPlugin.cssoMinify
  • CssMinimizerPlugin.cleanCssMinify
  • CssMinimizerPlugin.esbuildMinify
  • CssMinimizerPlugin.lightningCssMinify (previouslyCssMinimizerPlugin.parcelCssMinify, the package was renamed, but we keep it for backward compatibility)
  • async (data, inputMap, minimizerOptions) => {return {code: "a{color: red}", map: "...", warnings: [], errors: []}}

[!WARNING]

Always use require inside minify function when parallel option enabled.

Function

webpack.config.js

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

Array

If an array of functions is passed to the minify option, the minimizerOptions must also be an array. The function index in the minify array corresponds to the options object with the same index in the minimizerOptions array.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: [
          {}, // Options for the first function (CssMinimizerPlugin.cssnanoMinify)
          {}, // Options for the second function (CssMinimizerPlugin.cleanCssMinify)
          {}, // Options for the third function
        ],
        minify: [
          CssMinimizerPlugin.cssnanoMinify,
          CssMinimizerPlugin.cleanCssMinify,
          async (data, inputMap, minimizerOptions) => {
            // To do something
            return {
              code: `a{color: red}`,
              map: `{"version": "3", ...}`,
              warnings: [],
              errors: [],
            };
          },
        ],
      }),
    ],
  },
};

minimizerOptions

Type: Object|Array<Object> Default: { preset: 'default' }

Cssnano optimisations options.

Object

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

Array

The function index in the minify array corresponds to the options object with the same index in the minimizerOptions array. If you use minimizerOptions like object, all minify function accept it.

If a parallelization is enabled, the packages in minimizerOptions must be required via strings (packageName or require.resolve(packageName)). In this case, we shouldn't use require/import.

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

Type: Object Default: { from: assetName }

Allows filtering options processoptions for the cssnano. The parser, stringifier and syntax can be either a function or a string indicating the module that will be imported.

[!WARNING]

If a function is passed, the parallel option must be disabled..

import sugarss from "sugarss";

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        parallel: false,
        minimizerOptions: {
          processorOptions: {
            parser: sugarss,
          },
        },
      }),
    ],
  },
};
module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minimizerOptions: {
          processorOptions: {
            parser: "sugarss",
          },
        },
      }),
    ],
  },
};

warningsFilter

Type: Function<(warning, file, source) -> Boolean> Default: () => true

Allow filtering css-minimizer warnings (By default cssnano). Return true to keep the warning, a falsy value (false/null/undefined) otherwise.

[!WARNING]

The source argument will contain undefined if you don't use source maps.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        warningsFilter: (warning, file, source) => {
          if (/Dropping unreachable code/i.test(warning)) {
            return true;
          }

          if (/file\.css/i.test(file)) {
            return true;
          }

          if (/source\.css/i.test(source)) {
            return true;
          }

          return false;
        },
      }),
    ],
  },
};

Examples

Use sourcemaps

Don't forget to enable sourceMap options for all loaders.

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

module.exports = {
  devtool: "source-map",
  module: {
    rules: [
      {
        test: /.s?css$/,
        use: [
          MiniCssExtractPlugin.loader,
          { loader: "css-loader", options: { sourceMap: true } },
          { loader: "sass-loader", options: { sourceMap: true } },
        ],
      },
    ],
  },
  optimization: {
    minimizer: [new CssMinimizerPlugin()],
  },
  plugins: [new MiniCssExtractPlugin()],
};

Remove all comments

Remove all comments (including comments starting with /*!).

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

Using custom minifier csso

webpack.config.js

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

Using custom minifier clean-css

webpack.config.js

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

Using custom minifier esbuild

webpack.config.js

module.exports = {
  // Uncomment if you need source maps
  // devtool: "source-map",
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minify: CssMinimizerPlugin.esbuildMinify,
      }),
    ],
  },
};

Using custom minifier lightningcss, previously @parcel/css

webpack.config.js

module.exports = {
  // Uncomment if you need source maps
  // devtool: "source-map",
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minify: CssMinimizerPlugin.lightningCssMinify,
        // Uncomment this line for options
        // minimizerOptions: { targets: { ie: 11 }, drafts: { nesting: true } },
      }),
    ],
  },
};

Using custom minifier swc

webpack.config.js

module.exports = {
  // Uncomment if you need source maps
  // devtool: "source-map",
  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin({
        minify: CssMinimizerPlugin.swcMinify,
        // Uncomment this line for options
        // minimizerOptions: {},
      }),
    ],
  },
};

Contributing

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

CONTRIBUTING

License

MIT

DefinePlugin

DefinePlugin을 사용하면 컴파일 타임에 구성할 수 있는 전역 상수를 만들 수 있습니다. 이는 개발 빌드와 프로덕션 빌드 간에 서로 다른 동작을 하고 싶을 때 유용합니다. 개발 빌드에서 로깅을 수행하지만, 프로덕션 빌드에서는 수행하지 않는 경우 전역 상수를 사용하여 로깅을 수행할지 여부를 결정할 수 있습니다. 이것이 DefinePlugin가 유용한 이유입니다. 이 플러그인을 설정하고 개발 및 프로덕션 빌드 환경을 잊어버리세요.

new webpack.DefinePlugin({
  // Definitions...
});

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

기능 플래그를 사용하여 프로덕션/개발 빌드 기능을 활성화/비활성화 할 수 있습니다.

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

Service URLs

프로덕션/개발 빌드에서 서로 다른 서비스 URL을 사용할 수 있습니다.

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

Runtime values via runtimeValue

function (getterFunction, [string] | true | object) => getterFunction()

파일에 의존하는 값으로 변수를 정의할 수 있으며 이러한 파일이 파일 시스템에서 변경 될 때 재평가 됩니다. 이는 감시된 파일이 변경될 때 webpack이 재빌드 됨을 의미합니다.

webpack.DefinePlugin.runtimeValue 함수에는 두 가지 인자가 있습니다.

  • 첫 번째 인자는 정의에 할당할 값을 반환 해야 하는 function(module, key, version)입니다.

  • 두 번째 인자는 감시할 파일 경로의 배열이거나 모듈을 캐시 할 수 없음으로 표시하는 true 플래그일 수 있습니다. 5.26.0 버전부터는 아래의 속성을 가진 객체 인자를 사용할 수 있습니다.

    • fileDependencies?: string[] 함수가 의존하는 파일 목록입니다.
    • contextDependencies?: string[] 함수가 의존하는 디렉터리 목록입니다.
    • missingDependencies?: string[] 함수가 의존하는 존재하지 않는 파일 목록입니다.
    • buildDependencies?: string[] 함수가 의존하는 빌드 의존성 목록입니다.
    • version?: string | () => string 함수의 버전입니다.
const fileDep = path.resolve(__dirname, 'sample.txt');

new webpack.DefinePlugin({
  BUILT_AT: webpack.DefinePlugin.runtimeValue(Date.now, {
    fileDependencies: [fileDep],
  }),
});

BUILT_AT의 값은 'sample.txt'가 파일 시스템에서 마지막으로 업데이트된 시간입니다. (예: 1597953013291)

DllPlugin

DllPluginDllReferencePlugin은 빌드 시간 성능을 크게 향상시키는 방식으로 번들을 분할하는 수단을 제공합니다. "DLL"이라는 용어는 원래 Microsoft에서 도입한 동적 링크 라이브러리를 나타냅니다.

DllPlugin

이 플러그인은 dll 전용 번들을 생성하기 위해 단독으로 별도의 webpack 설정에서 사용됩니다. 의존성을 매핑하기 위해 DllReferencePlugin에서 사용하는 manifest.json파일을 생성합니다.

  • context (선택): 매니페스트 파일의 요청 컨텍스트 (기본값은 webpack 컨텍스트)
  • format (boolean = false): true인 경우 매니페스트 json 파일(출력)이 형식화됩니다.
  • name: 노출된 dll 함수의 이름 (TemplatePaths: [fullhash], [chunkhash], [contenthash], & [name] )
  • path: 매니페스트 json 파일의 절대 경로 (출력)
  • entryOnly (boolean = true): true인 경우 엔트리 포인트만 노출됩니다.
  • type: dll 번들의 유형
new webpack.DllPlugin(options);

주어진 경로에 기록되는 manifest.json을 생성합니다. 여기에는 require와 import 요청에서 모듈 id로의 매핑이 포함됩니다. 이는 DllReferencePlugin 에서 사용됩니다.

이 플러그인을 output.library옵션과 결합하여 dll 함수를 노출(전역 범위로 확대)합니다.

DllReferencePlugin

이 플러그인은 기본 webpack 설정에서 사용되며, 사전 빌드된 의존성을 require 하기 위해 dll 전용 번들을 참조합니다.

  • context: 매니페스트(또는 콘텐츠 프로퍼티)에 있는 요청의 (절대 경로) 컨텍스트
  • extensions: dll 번들의 모듈을 해결하는데 사용되는 확장입니다(‘유효범위’를 사용할 때만 사용).
  • manifest : contentname을 포함하는 객체 또는 컴파일 시 로드될 JSON 매니페스트의 절대 경로에 대한 문자열
  • content (선택): 요청에서 모듈 id 로의 매핑(기본값은 manifest.content)
  • name (선택): dll이 노출되는 식별자(기본값은 manifest.name)(externals 참조)
  • scope (선택): dll의 콘텐츠에 접근하는데 사용되는 접두사
  • sourceType (선택): dll이 노출되는 방법(libraryTarget)
new webpack.DllReferencePlugin(options);

dll 매니페스트 파일을 참조하여 의존성 이름을 모듈 id에 매핑한 다음, 내부 __webpack_require__함수를 사용하여 필요에 따라 요청합니다.

Modes

이 플러그인은 scopedmapped 두 가지 모드에서 사용할 수 있습니다.

Scoped Mode

dll의 콘텐츠는 모듈 접두사 아래에서 접근 가능합니다. 즉, scope = 'xyz'로 dll의 파일 abcrequire('xyz/abc')를 통해 접근할 수 있습니다.

Mapped Mode

dll의 콘텐츠는 현재 디렉터리에 매핑됩니다. 필요한 파일이 dll의 파일과 확인 후 일치하는 경우, dll의 파일이 대신 사용됩니다.

이것은 dll 번들의 모든 파일을 해석한 후 발생하기 때문에 dll 번들의 사용자에 대해 동일한 경로를 사용할 수 있어야 합니다. 즉, dll에 lodash 가 포함되어 있고 abc 파일이 있으면 require('lodash')require('./abc') 가 메인 번들로 빌드되지 않고 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',
});

Examples

VendorUser

두 개의 개별 예제 폴더로, 유효범위와 컨텍스트를 보여줍니다.

References

Source

Tests

EnvironmentPlugin

EnvironmentPlugin을 사용해 process.env 키에 DefinePlugin을 간단히 적용할 수 있습니다.

Usage

EnvironmentPlugin은 키로 구성된 배열 혹은 키에 기본값이 매핑된 객체를 받습니다.

new webpack.EnvironmentPlugin(['NODE_ENV', 'DEBUG']);

이는 다음과 같은 DefinePlugin 적용과 동일합니다.

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

또는, EnvironmentPlugin은 키에 기본값을 매핑한 객체를 지원합니다. 키가 process.env에 정의되지 않은 경우에는 기본값을 사용합니다.

new webpack.EnvironmentPlugin({
  NODE_ENV: 'development', // process.env.NODE_ENV가 정의되지 않은 경우 'development'를 사용하세요.
  DEBUG: false,
});

Example:

지금까지 구성해온 EnvironmentPlugin 설정을 테스트 파일 entry.js에 적용했을 때 어떻게 동작하는지 알아봅시다.

if (process.env.NODE_ENV === 'production') {
  console.log('Welcome to production');
}
if (process.env.DEBUG) {
  console.log('Debugging output');
}

빌드하기 위해 터미널에서 NODE_ENV=production webpack을 실행했을 때 entry.js는 다음과 같습니다.

if ('production' === 'production') {
  // <-- NODE_ENV의 'production'이 사용됩니다.
  console.log('Welcome to production');
}
if (false) {
  // <-- 기본값이 사용됩니다.
  console.log('Debugging output');
}

DEBUG=false webpack을 실행하면 다음과 같습니다.

if ('development' === 'production') {
  // <-- 기본값이 사용됩니다.
  console.log('Welcome to production');
}
if ('false') {
  // <-- DEBUG의 'false'가 사용됩니다.
  console.log('Debugging output');
}

Use Case: Git Version

다음과 같은 EnvironmentPlugin 설정은 저장소의 마지막 커밋에 따른 process.env.GIT_VERSION (예시 "v5.4.0-2-g25139f57f")과 process.env.GIT_AUTHOR_DATE (예시 "2020-11-04T12:25:16+01:00")를 제공합니다.

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

써드 파티 DotenvPlugin (dotenv-webpack)을 사용해 dotenv 변수를 사용할 수 있습니다.

// .env
DB_HOST=127.0.0.1
DB_PASS=foobar
S3_API=mysecretkey
new Dotenv({
  path: './.env', // .env 파일 경로 (기본값)
  safe: true, // .env.example 로드 (기본값은 dotenv-safe를 사용하지 않는 "false")
});

EslintWebpackPlugin

npm node tests coverage discussion size

This version of eslint-webpack-plugin only works with webpack 5. For the webpack 4, see the 2.x branch.

This plugin uses eslint to find and fix problems in your JavaScript code

Getting Started

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

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

or

yarn add -D eslint-webpack-plugin

or

pnpm add -D eslint-webpack-plugin

[!NOTE]

You also need to install eslint >= 8 from npm, if you haven't already:

npm install eslint --save-dev

or

yarn add -D eslint

or

pnpm add -D eslint

Then add the plugin to your webpack config. For example:

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

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

Options

You can pass eslint options.

[!NOTE]

The config option you provide will be passed to the ESLint class. This is a different set of options than what you'd specify in package.json or .eslintrc. See the eslint docs for more details.

[!WARNING]

In eslint-webpack-plugin version 1 the options were passed to the now deprecated CLIEngine.

cache

  • Type:
type cache = boolean;
  • Default: true

The cache is enabled by default to decrease execution time.

cacheLocation

  • Type:
type cacheLocation = string;
  • Default: node_modules/.cache/eslint-webpack-plugin/.eslintcache

Specify the path to the cache location. Can be a file or a directory.

configType

  • Type:
type configType = 'flat' | 'eslintrc';
  • Default: eslintrc

Specify the type of configuration to use with ESLint.

  • eslintrc is the classic configuration format available in most ESLint versions.
  • flat is the new format introduced in ESLint 8.21.0.

The new configuration format is explained in its own documentation.

This configuration format being considered as experimental, it is not exported in the main ESLint module in ESLint 8. You need to set your eslintPath to eslint/use-at-your-own-risk for this config format to work.

context

  • Type:
type context = string;
  • Default: compiler.context

A string indicating the root of your files.

eslintPath

  • Type:
type eslintPath = string;
  • Default: eslint

Path to eslint instance that will be used for linting. If the eslintPath is a folder like a official eslint, or specify a formatter option. now you don't have to install eslint.

extensions

  • Type:
type extensions = string | Array<string>;
  • Default: 'js'

Specify extensions that should be checked.

exclude

  • Type:
type exclude = string | Array<string>;
  • Default: 'node_modules'

Specify the files and/or directories to exclude. Must be relative to options.context.

resourceQueryExclude

  • Type:
type resourceQueryExclude = RegExp | Array<RegExp>;
  • Default: []

Specify the resource query to exclude.

files

  • Type:
type files = string | Array<string>;
  • Default: null

Specify directories, files, or globs. Must be relative to options.context. Directories are traversed recursively looking for files matching options.extensions. File and glob patterns ignore options.extensions.

fix

  • Type:
type fix = boolean;
  • Default: false

Will enable ESLint autofix feature.

Be careful: this option will change source files.

formatter

  • Type:
type formatter = string| (
  results:  Array<import('eslint').ESLint.LintResult>,
  data?: import('eslint').ESLint.LintResultData | undefined
) => string
  • Default: 'stylish'

Accepts a function that will have one argument: an array of eslint messages (object). The function must return the output as a string. You can use official eslint formatters.

lintDirtyModulesOnly

  • Type:
type lintDirtyModulesOnly = boolean;
  • Default: false

Lint only changed files, skip lint on start.

threads

  • Type:
type threads = boolean | number;
  • Default: false

Will run lint tasks across a thread pool. The pool size is automatic unless you specify a number.

Errors and Warning

By default the plugin will auto adjust error reporting depending on eslint errors/warnings counts. You can still force this behavior by using emitError or emitWarning options:

emitError

  • Type:
type emitError = boolean;
  • Default: true

The errors found will always be emitted, to disable set to false.

emitWarning

  • Type:
type emitWarning = boolean;
  • Default: true

The warnings found will always be emitted, to disable set to false.

failOnError

  • Type:
type failOnError = boolean;
  • Default: true

Will cause the module build to fail if there are any errors, to disable set to false.

failOnWarning

  • Type:
type failOnWarning = boolean;
  • Default: false

Will cause the module build to fail if there are any warnings, if set to true.

quiet

  • Type:
type quiet = boolean;
  • Default: false

Will process and report errors only and ignore warnings, if set to true.

outputReport

  • Type:
type outputReport =
  | boolean
  | {
      filePath?: string | undefined;
      formatter?:
        | (
            | string
            | ((
                results: Array<import('eslint').ESLint.LintResult>,
                data?: import('eslint').ESLint.LintResultData | undefined,
              ) => string)
          )
        | undefined;
    };
  • Default: false

Write the output of the errors to a file, for example a checkstyle xml file for use for reporting on Jenkins CI.

The filePath is an absolute path or relative to the webpack config: output.path. You can pass in a different formatter for the output file, if none is passed in the default/configured formatter will be used.

Changelog

Changelog

License

MIT

EvalSourceMapDevToolPlugin

EvalSourceMapDevToolPlugin을 사용하면 소스맵 생성을 보다 세밀하게 제어할 수 있습니다. 또한 devtool 설정 옵션의 특정한 세팅에 의해 자동으로 활성화됩니다.

new webpack.EvalSourceMapDevToolPlugin(options);

Options

다음과 같은 옵션이 지원됩니다.

  • test (string|RegExp|array): 모듈의 확장자를 기반으로 하는 소스맵을 포함합니다(기본값은 .js.css).

  • include (string|RegExp|array): 주어진 값과 일치하는 모듈 경로에 대한 소스맵을 포함합니다.

  • exclude (string|RegExp|array): 소스맵 생성에서 주어진 값과 일치하는 모듈을 제외합니다.

  • append (string|function): 원래 애셋에 주어진 값을 추가합니다. 보통 #sourceMappingURL 을 주석으로 합니다. [url]은 소스맵 파일의 URL로 대체됩니다.

    버전 5.84.0부터 webpack은 경로와 애셋 정보 객체를 인수로 받아들이고 문자열을 반환하는 'append' 옵션을 허용합니다.

    (pathData: PathData, assetInfo?: AssetInfo) => string;
  • moduleFilenameTemplate (string): output.devtoolModuleFilenameTemplate을 참조하세요.

  • module (boolean): 로더가 소스맵을 생성해야 하는지 여부를 나타냅니다(기본값은 true).

  • columns (boolean): 열 매핑을 사용해야 하는지 여부를 나타냅니다(기본값은 true).

  • protocol (string): 사용자가 기본 프로토콜(webpack-internal://)을 오버라이드 할 수 있습니다.

Examples

다음 예시는 EvalSourceMapDevToolPlugin이 흔히 사용되는 사례를 보여줍니다.

Basic Use Case

다음 코드를 사용하여 설정 옵션 devtool: eval-source-map을 동등한 커스텀 플러그인 설정으로 바꿀 수 있습니다.

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

Exclude Vendor Maps

다음 코드는 vendor.js 번들에 있는 모든 모듈에 대한 소스맵을 제외합니다.

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

HashedModuleIdsPlugin

이 플러그인은 해시가 모듈의 상대 경로를 기반으로 해 모듈 ID로 4개의 문자열이 생성됩니다. 프로덕션에 사용할 것을 권장합니다.

new webpack.ids.HashedModuleIdsPlugin({
  // 옵션...
});

Options

이 플러그인은 다음 옵션을 지원합니다:

  • context: 이름을 만들기 위한 컨텍스트 디렉터리 (절대 경로).
  • hashFunction: 사용할 해싱 알고리즘, 기본 값은 'md4'입니다. Node.JS의 crypto.createHash의 모든 기능이 지원됩니다.
  • hashDigest: 해시를 생성할 때 사용할 인코딩, 기본 값은 'base64'입니다. Node.JS의 hash.digest의 모든 인코딩이 지원됩니다.
  • hashDigestLength: 사용할 해시 다이제스트의 접두사 길이, 기본 값은 4입니다. 생성된 일부 ID는 모듈 ID 충돌을 피하기 위해 여기에서 지정된 것보다 길 수 있습니다.

Usage

다음은 이 플러그인을 사용하는 방법의 예시입니다:

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

HotModuleReplacementPlugin

HMR로 알려져 있는 Hot Module Replacement을 활성화합니다.

Basic Usage

HMR을 활성화하는 것은 간단하며 대부분의 경우 옵션이 필요하지 않습니다.

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

HtmlMinimizerWebpackPlugin

npm node tests cover discussion size

This plugin can use 3 tools to optimize and minify your HTML:

  • swc - very fast Rust-based platform for the Web.
  • html-minifier-terser (by default) - JavaScript-based HTML minifier.
  • @minify-html/node - A Rust HTML minifier meticulously optimised for speed and effectiveness, with bindings for other languages.

Getting Started

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

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

or

yarn add -D html-minimizer-webpack-plugin

or

pnpm add -D html-minimizer-webpack-plugin

Additional step: If you want to use @swc/html you need to install it:

npm install @swc/html --save-dev

or

yarn add -D @swc/html

or

pnpm add -D @swc/html

Additional step: If you want to use @minify-html/node you need to install it:

npm install @minify-html/node --save-dev

or

yarn add -D @minify-html/node

or

pnpm add -D @minify-html/node

Then add the plugin to your webpack configuration. For example:

webpack.config.js

const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          context: path.resolve(__dirname, "dist"),
          from: "./src/*.html",
        },
      ],
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
      // `...`

      // For `html-minifier-terser`:
      //
      new HtmlMinimizerPlugin(),

      // For `@swc/html`:
      //
      // HTML documents - HTML documents with `Doctype` and `<html>/`<head>`/`<body>` tags
      //
      // Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L5
      //
      // new HtmlMinimizerPlugin({
      //   minify: HtmlMinimizerPlugin.swcMinify,
      //   minimizerOptions: {}
      // })
      //
      //
      // HTML fragments - HTML fragments, i.e. HTML files without doctype or used in `<template>` tags or HTML parts which injects into another HTML parts
      //
      // Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L38
      //
      // new HtmlMinimizerPlugin({
      //   minify: HtmlMinimizerPlugin.swcMinifyFragment,
      //   minimizerOptions: {}
      // })
    ],
  },
};

This will enable HTML optimization only in production mode. If you want to run it also in development set the optimization.minimize option to true.

And run webpack via your preferred method.

[!NOTE]

Removing and collapsing spaces in the tools differ (by default).

  • @swc/html - remove and collapse whitespaces only in safe places (for example - around html and body elements, inside the head element and between metadata elements - <meta>/script/link/etc.)
  • html-minifier-terser - always collapse multiple whitespaces to 1 space (never remove it entirely), but you can change it using options
  • @minify-html/node - please read documentation https://github.com/wilsonzlin/minify-html#whitespace

Options

test

Type:

type test = string | RegExp | Array<string | RegExp>;

Default: /\.html(\?.*)?$/i

Test to match files against.

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

include

Type:

type include = string | RegExp | Array<string | RegExp>;

Default: undefined

Files to include.

webpack.config.js

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

exclude

Type:

type exclude = string | RegExp | Array<string | RegExp>;

Default: undefined

Files to exclude.

webpack.config.js

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

parallel

Type:

type parallel = undefined | boolean | number;

Default: true

Use multi-process parallel running to improve the build speed. Default number of concurrent runs: os.cpus().length - 1.

[!NOTE]

Parallelization can speed up your build significantly and is therefore highly recommended.

boolean

Enable/disable multi-process parallel running.

webpack.config.js

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

number

Enable multi-process parallel running and set number of concurrent runs.

webpack.config.js

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

minify

Type:

type minify =
  | ((
      data: { [file: string]: string },
      minimizerOptions: {
        [key: string]: any;
      },
    ) => {
      code: string;
      errors?: unknown[] | undefined;
      warnings?: unknown[] | undefined;
    })
  | ((
      data: { [file: string]: string },
      minimizerOptions: {
        [key: string]: any;
      },
    ) => {
      code: string;
      errors?: unknown[] | undefined;
      warnings?: unknown[] | undefined;
    })[];

Default: HtmlMinimizerPlugin.htmlMinifierTerser

Allows you to override default minify function. By default, plugin uses html-minifier-terser package.

We currently support:

  • HtmlMinimizerPlugin.swcMinify (used to compress HTML documents, i.e. with HTML doctype and <html>/<body>/<head> tags)
  • HtmlMinimizerPlugin.swcMinifyFragment (used to compress HTML fragments, i.e. when you have part of HTML which will be inserted into another HTML parts)
  • HtmlMinimizerPlugin.htmlMinifierTerser
  • HtmlMinimizerPlugin.minifyHtmlNode

[!NOTE]

The difference between swcMinify and swcMinifyFragment is the error reporting. You will get errors (invalid or broken syntax) if you have them in your HTML document or fragment. Which allows you to see all the errors and problems at the build stage.

Useful for using and testing unpublished versions or forks.

[!WARNING]

Always use require 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:

type minimizerOptions =
  | {
      [key: string]: any;
    }
  | Array<{
      [key: string]: any;
    }>;

Default: { caseSensitive: true, collapseWhitespace: true, conservativeCollapse: true, keepClosingSlash: true, minifyCSS: true, minifyJS: true, removeComments: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, }

Html-minifier-terser optimizations options.

object

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        minimizerOptions: {
          collapseWhitespace: false,
        },
      }),
    ],
  },
};

array

The function index in the minify array corresponds to the options object with the same index in the minimizerOptions array. If you use minimizerOptions like object, all minify function accept it.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        minimizerOptions: [
          // Options for the first function (HtmlMinimizerPlugin.htmlMinifierTerser)
          {
            collapseWhitespace: true,
          },
          // Options for the second function
          {},
        ],
        minify: [
          HtmlMinimizerPlugin.htmlMinifierTerser,
          (data, minimizerOptions) => {
            const [[filename, input]] = Object.entries(data);
            // To do something
            return {
              code: `optimised code`,
              warnings: [],
              errors: [],
            };
          },
        ],
      }),
    ],
  },
};

Examples

swc/html

Available options.

HTML Documents:

const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          context: path.resolve(__dirname, "dist"),
          from: "./src/*.html",
        },
      ],
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        minify: HtmlMinimizerPlugin.swcMinify,
        minimizerOptions: {
          // Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L5
        },
      }),
    ],
  },
};

HTML Fragments:

const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          context: path.resolve(__dirname, "dist"),
          from: "./src/*.html",
        },
      ],
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        test: /\.template\.html$/i,
        minify: HtmlMinimizerPlugin.swcMinifyFragment,
        minimizerOptions: {
          // Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L38
        },
      }),
    ],
  },
};

@minify-html/node

Available options.

HTML Documents:

const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          context: path.resolve(__dirname, "dist"),
          from: "./src/*.html",
        },
      ],
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin({
        minify: HtmlMinimizerPlugin.minifyHtmlNode,
        minimizerOptions: {
          // Options - https://github.com/wilsonzlin/minify-html#minification
        },
      }),
    ],
  },
};

You can use multiple HtmlMinimizerPlugin plugins to compress different files with the different minify function.

Contributing

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

CONTRIBUTING

License

MIT

HtmlWebpackPlugin

HtmlWebpackPlugin은 webpack 번들을 제공하는 HTML 파일 생성을 단순화합니다. 이 플러그인은 매번 컴파일에 변경되는 해시로 된 파일 이름을 가진 webpack 번들에 특히 유용합니다. 플러그인이 HTML 파일을 생성하도록 하거나 lodash 템플릿을 사용하여 나만의 템플릿을 제공하거나 나만의 로더를 사용할 수 있습니다.

Installation

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

Basic Usage

플러그인은 script 태그를 사용하여 body에 모든 webpack 번들을 포함하는 HTML5 파일을 생성합니다. 적용은 아래와 같이 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> 태그로 포함됩니다.

Configuration

모든 설정 옵션은 plugin 문서를 참고하세요.

Third party addons

플러그인은 추가 기능을 지원합니다. 목록은 해당 문서를 참고하세요.

IgnorePlugin

IgnorePlugin은 정규 표현식 또는 필터 함수와 일치하는 import 또는 require 호출에 대한 모듈 생성을 방지합니다.

Using regular expressions

  • resourceRegExp: 리소스 테스트를 위한 정규 표현식
  • contextRegExp: (선택) 컨텍스트 (디렉터리) 테스트를 위한 정규 표현식
new webpack.IgnorePlugin({ resourceRegExp, contextRegExp });

Using filter functions

  • checkResource (resource, context)resourcecontext를 인수로 받는 필터 함수로, 불리언 값을 반환해야 합니다.
new webpack.IgnorePlugin({
  checkResource(resource) {
    // 리소스를 사용합니다
    return true | false;
  },
});

Example of ignoring Moment Locales

moment 2.18 부터, 모든 로케일이 코어 라이브러리와 함께 번들로 제공됩니다 (깃허브 이슈를 참고하세요).

IgnorePlugin에 전달된 resourceRegExp 파라미터는 import 또는 require 되는 해석된 파일 이름 혹은 절대 모듈 이름에 대해 테스트 되지 않고, 가져오기가 실행되는 소스 코드 내에서 require 또는 import로 전달된 문자열 에 대해 테스트 됩니다. 예를 들어 node_modules/moment/locale/*.js를 제외하려는 경우 다음과 같은 작업이 수행되지 않습니다.

-new webpack.IgnorePlugin({ resourceRegExp: /moment\/locale\// });

moment는 아래의 코드로 가져오기 때문입니다.

require('./locale/' + name);

첫 번째 정규 표현식은 './locale/' 문자열과 일치해야 합니다. 그다음 두 번째 contextRegExp 파라미터를 사용하여 가져오기가 수행된 특정 디렉터리를 선택합니다. 다음은 로케일 파일이 무시되는 경우입니다.

new webpack.IgnorePlugin({
  resourceRegExp: /^\.\/locale$/,
  contextRegExp: /moment$/,
});

이는 'moment'로 끝나는 디렉터리에서 './locale'과 일치하는 모든 require 문이 무시됨을 의미합니다.

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 tests cover discussion size

Getting Started

This plugin can use 4 tools to optimize/generate images:

  • imagemin - optimize your images by default, since it is stable and works with all types of images
  • DEPRECATED squoosh - while working in experimental mode with .jpg, .jpeg, .png, .webp, .avif file types.
  • sharp - High performance Node.js image processing, the fastest module to resize and compress JPEG, PNG, WebP, AVIF and TIFF images. Uses the libvips library.
  • svgo - tool for optimizing SVG vector graphics files. Supports only SVG files minification.

[!WARNING]

By default we don't install anything

Install optimize/generate tool

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

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

[!WARNING]

imagemin uses plugin to optimize/generate images, so you need to install them too

npm install image-minimizer-webpack-plugin @squoosh/lib --save-dev
npm install image-minimizer-webpack-plugin sharp --save-dev
npm install image-minimizer-webpack-plugin svgo --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");

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

DEPRECATED 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 of @squoosh/lib package. The default values and supported file types for each option can be found in the codecs.ts file under codecs.

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
      {
        test: /\.(jpe?g|png)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.squooshMinify,
          options: {
            // Your options for `squoosh`
          },
        },
      }),
    ],
  },
};

Recommended squoosh options for lossless optimization

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

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
      {
        test: /\.(jpe?g|png)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.squooshMinify,
          options: {
            encodeOptions: {
              mozjpeg: {
                // That setting might be close to lossless, but it’s not guaranteed
                // https://github.com/GoogleChromeLabs/squoosh/issues/85
                quality: 100,
              },
              webp: {
                lossless: 1,
              },
              avif: {
                // https://github.com/GoogleChromeLabs/squoosh/blob/dev/codecs/avif/enc/README.md
                cqLevel: 0,
              },
            },
          },
        },
      }),
    ],
  },
};

Optimize with sharp

npm install sharp --save-dev

Recommended sharp options for lossy optimization

For lossy optimization we recommend using the default settings of sharp package. The default values and supported file types for each option can be found in the sharp documentation.

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
      {
        test: /\.(jpe?g|png)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.sharpMinify,
          options: {
            encodeOptions: {
              // Your options for `sharp`
              // https://sharp.pixelplumbing.com/api-output
            },
          },
        },
      }),
    ],
  },
};

Recommended sharp options for lossless optimization

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

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
      {
        test: /\.(jpe?g|png)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.sharpMinify,
          options: {
            encodeOptions: {
              jpeg: {
                // https://sharp.pixelplumbing.com/api-output#jpeg
                quality: 100,
              },
              webp: {
                // https://sharp.pixelplumbing.com/api-output#webp
                lossless: true,
              },
              avif: {
                // https://sharp.pixelplumbing.com/api-output#avif
                lossless: true,
              },

              // png by default sets the quality to 100%, which is same as lossless
              // https://sharp.pixelplumbing.com/api-output#png
              png: {},

              // gif does not support lossless compression at all
              // https://sharp.pixelplumbing.com/api-output#gif
              gif: {},
            },
          },
        },
      }),
    ],
  },
};

Optimize with svgo

npm install svgo --save-dev

Recommended svgo options for optimization

For optimization we recommend using the options listed below in minimizer.options.encodeOptions. The default values for plugins can be found in the svgo plugins source code.

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
      {
        test: /\.(svg)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.svgoMinify,
          options: {
            encodeOptions: {
              // Pass over SVGs multiple times to ensure all optimizations are applied. False by default
              multipass: true,
              plugins: [
                // set of built-in plugins enabled by default
                // see: https://github.com/svg/svgo#default-preset
                "preset-default",
              ],
            },
          },
        },
      }),
    ],
  },
};

Advanced setup

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

By default, plugin configures loader (please use the loader option if you want to disable this behaviour), therefore you should not setup standalone loader when you use a plugin setup.

Loader optimizes or generates images using options, so inlined images via data URI (i.e. data:) will be optimized or generated too, not inlined images will be optimized too.

Query Parameters (only squoosh and sharp currently)

The plugin supports the following query parameters:

  • width/w - allows you to set the image width

  • height/h - allows you to set the image height

  • as - to specify the preset option

    Only supported for sharp currently:

  • unit/u - can be px or percent and allows you to resize by a percentage of the image's size.

Examples:

const myImage1 = new URL("image.png?width=150&height=120", import.meta.url);
const myImage2 = new URL("image.png?w=150&h=120", import.meta.url);
// You can omit one of the parameters to auto-scale
const myImage3 = new URL("image.png?w=150", import.meta.url);
// It works with the `preset` query parameter
const myImage4 = new URL("image.png?as=webp&w=150&h=120", import.meta.url);
// You can use `auto` to reset `width` or `height` from the `preset` option
const myImage5 = new URL("image.png?as=webp&w=150&h=auto", import.meta.url);
// You can use `unit` to get the non-retina resize of images that are retina sized
const myImage6 = new URL("image.png?width=50&unit=percent", import.meta.url);
.class {
  background: url("./image.png?width=150&height=120");
}
<picture>
  <source srcset="photo.jpg?as=avif&width=150&height=120" type="image/avif" />
  <source srcset="photo.jpg?as=webp&width=150&height=120" type="image/webp" />
  <img src="photo.jpg?width=150&height=120" alt="photo" />
</picture>

[!NOTE]

You need to setup avif and webp presets, example for webp.

Standalone Loader

Documentation: Using loaders.

In your webpack.config.js, add the ImageMinimizerPlugin.loader and specify the asset modules options (if you use images in import):

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: "asset",
      },
      // We recommend using only for the "production" mode
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: [
          {
            loader: ImageMinimizerPlugin.loader,
            enforce: "pre",
            options: {
              minimizer: {
                implementation: ImageMinimizerPlugin.imageminMinify,
                options: {
                  plugins: [
                    "imagemin-gifsicle",
                    "imagemin-mozjpeg",
                    "imagemin-pngquant",
                    "imagemin-svgo",
                  ],
                },
              },
            },
          },
        ],
      },
    ],
  },
};

Standalone Plugin

Documentation: Using plugins.

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      // You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: "asset",
      },
    ],
  },
  optimization: {
    minimizer: [
      // Extend default minimizer, i.e. `terser-webpack-plugin` for JS
      "...",
      // We recommend using only for the "production" mode
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
        // Disable `loader`
        loader: false,
      }),
    ],
  },
};

Plugin Options

test

Type:

type test = string | RegExp | Array<string | RegExp>;

Default: /\.(jpe?g\|png\|gif\|tif\|webp\|svg\|avif)\$/i

Test to match files against.

webpack.config.js

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

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

include

Type:

type include = string | RegExp | Array<string | RegExp>;

Default: undefined

Files to include.

webpack.config.js

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

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

exclude

Type:

type exclude = string | RegExp | Array<string | RegExp>;

Default: undefined

Files to exclude.

webpack.config.js

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

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

minimizer

Type:

type minimizer =
  | {
      implementation: (
        original: {
          filename: string;
          data: Buffer;
          warnings: Array<Error>;
          errors: Array<Error>;
          info: import("webpack").AssetInfo;
        },
        options?:
          | {
              [key: string]: any;
            }
          | undefined,
      ) => Promise<{
        filename: string;
        data: Buffer;
        warnings: Array<Error>;
        errors: Array<Error>;
        info: import("webpack").AssetInfo;
      }> & {
        setup?: (() => void) | undefined;
        teardown?: (() => void) | undefined;
      };
      options?:
        | {
            [key: string]: any;
          }
        | undefined;
      filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
      filename?:
        | string
        | ((
            pathData: {
              filename?: string | undefined;
            },
            assetInfo?: import("webpack").AssetInfo | undefined,
          ) => string)
        | undefined;
    }
  | Array<{
      implementation: (
        original: {
          filename: string;
          data: Buffer;
          warnings: Array<Error>;
          errors: Array<Error>;
          info: import("webpack").AssetInfo;
        },
        options?:
          | {
              [key: string]: any;
            }
          | undefined,
      ) => Promise<{
        filename: string;
        data: Buffer;
        warnings: Array<Error>;
        errors: Array<Error>;
        info: import("webpack").AssetInfo;
      }> & {
        setup?: (() => void) | undefined;
        teardown?: (() => void) | undefined;
      };
      options?:
        | {
            [key: string]: any;
          }
        | undefined;
      filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
      filename?:
        | string
        | ((
            pathData: {
              filename?: string | undefined;
            },
            assetInfo?: import("webpack").AssetInfo | undefined,
          ) => string)
        | undefined;
    }>;

Default: undefined

Allows to setup default minify function.

Available minimizers

  • ImageMinimizerPlugin.imageminMinify
  • DEPRECATED ImageMinimizerPlugin.squooshMinify
  • ImageMinimizerPlugin.sharpMinify
  • ImageMinimizerPlugin.svgoMinify

Single minimizer example for imagemin

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          // Implementation
          implementation: ImageMinimizerPlugin.imageminMinify,
          // Options
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};

More information and examples here.

DEPRECATED Single minimizer example for squoosh

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          // Implementation
          implementation: ImageMinimizerPlugin.squooshMinify,
          // Options
          options: {
            encodeOptions: {
              mozjpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};

More information and examples here.

Single minimizer example for sharp

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          // Implementation
          implementation: ImageMinimizerPlugin.sharpMinify,
          // Options
          options: {
            encodeOptions: {
              jpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};

More information and examples here.

Single minimizer example for user defined implementation

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: async (original, options) => {
            const inputExt = path.extname(original.filename).toLowerCase();

            if (inputExt !== ".xxx") {
              // Return `null` if the implementation does not support this file type
              return null;
            }

            let result;

            try {
              result = await minifyAndReturnBuffer(original.data);
            } catch (error) {
              // Store error and return `null` if there was an error
              original.errors.push(error);
              return null;
            }

            return {
              filename: original.filename,
              data: result,
              warnings: [...original.warnings],
              errors: [...original.errors],
              info: {
                ...original.info,
                // Please always set it to prevent double minification
                minimized: true,
                // Optional
                minimizedBy: ["custom-name-of-minimication"],
              },
            };
          },
          options: {
            // Custom options
          },
        },
      }),
    ],
  },
};

Multiple minimizers example

Allows to setup multiple minimizers.

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: [
          {
            // `sharp` will handle all bitmap formats (JPG, PNG, GIF, ...)
            implementation: ImageMinimizerPlugin.sharpMinify,

            // exclude SVG if implementation support it. Not required for `sharp`.
            // filter: (source, sourcePath) => !(/\.(svg)$/i.test(sourcePath)),

            options: {
              encodeOptions: {
                // Your options for `sharp`
                // https://sharp.pixelplumbing.com/api-output
              },
            },
          },
          {
            // `svgo` will handle vector images (SVG)
            implementation: ImageMinimizerPlugin.svgoMinify,
            options: {
              encodeOptions: {
                // Pass over SVGs multiple times to ensure all optimizations are applied. False by default
                multipass: true,
                plugins: [
                  // set of built-in plugins enabled by default
                  // see: https://github.com/svg/svgo#default-preset
                  "preset-default",
                ],
              },
            },
          },
        ],
      }),
    ],
  },
};

Minimizer options

implementation

Type:

type implementation = (
  original: {
    filename: string;
    data: Buffer;
    warnings: Array<Error>;
    errors: Array<Error>;
    info: import("webpack").AssetInfo;
  },
  options?: BasicTransformerOptions<T>,
) => Promise<{
  filename: string;
  data: Buffer;
  warnings: Array<Error>;
  errors: Array<Error>;
  info: import("webpack").AssetInfo;
}> & {
  setup?: (() => void) | undefined;
  teardown?: (() => void) | undefined;
};

Default: undefined

Configure the default implementation.

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          // Implementation
          implementation: ImageMinimizerPlugin.sharpMinify,
          // Options
          options: {
            encodeOptions: {
              jpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};
options

Type:

type options = {
  [key: string]: any;
};

Default: undefined

Options for the implementation option (i.e. options for imagemin/squoosh/sharp/custom implementation).

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.sharpMinify,
          // Options
          options: {
            encodeOptions: {
              jpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};
filter

Type:

type filter = (source: Buffer, sourcePath: string) => boolean | undefined;

Default: () => true

Allows filtering of images for optimization/generation.

Return true to optimize the image, false otherwise.

webpack.config.js

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

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

            return true;
          },
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};
filename

Type:

type filename =
  | string
  | ((
      pathData: {
        filename?: string | undefined;
      },
      assetInfo?: import("webpack").AssetInfo | undefined,
    ) => string)
  | undefined;

Default: undefined

Allows to set the filename. Supported values see in webpack template strings, File-level section.

We also support [width] and [height] placeholders (only sharp and squoosh).

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          filename: "optimized-[name][ext]",
          implementation: ImageMinimizerPlugin.sharpMinify,
          // Options
          options: {
            encodeOptions: {
              jpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};

Example function usage:

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          filename: () => "optimized-[name][ext]",
          implementation: ImageMinimizerPlugin.sharpMinify,
          // Options
          options: {
            encodeOptions: {
              jpeg: {
                quality: 90,
              },
            },
          },
        },
      }),
    ],
  },
};

generator

Type:

type generator = Array<{
  implementation: (
    original: {
      filename: string;
      data: Buffer;
      warnings: Array<Error>;
      errors: Array<Error>;
      info: import("webpack").AssetInfo;
    },
    options?:
      | {
          [key: string]: any;
        }
      | undefined,
  ) => Promise<{
    filename: string;
    data: Buffer;
    warnings: Array<Error>;
    errors: Array<Error>;
    info: import("webpack").AssetInfo;
  }> & {
    setup?: (() => void) | undefined;
    teardown?: (() => void) | undefined;
  };
  options?:
    | {
        [key: string]: any;
      }
    | undefined;
  filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
  filename?:
    | string
    | ((
        pathData: {
          filename?: string | undefined;
        },
        assetInfo?: import("webpack").AssetInfo | undefined,
      ) => string)
    | undefined;
  preset?: string | undefined;
  type?: "import" | "asset" | undefined;
}>;

Default: undefined

Allow to setup default generators. Useful if you need generate webp/avif/etc from other formats.

[!WARNING]

If no generator was found for the image (i.e. no ?as=webp was found in query params), the minimizer option will be used. Therefore, it is recommended to configure generator outputs optimized image.

[!WARNING]

The option will not work if you disable loader (i.e. set the loader option to false).

Available generators

  • ImageMinimizerPlugin.imageminGenerate
  • DEPRECATED ImageMinimizerPlugin.squooshGenerate
  • ImageMinimizerPlugin.sharpGenerate

Generator example for imagemin

Example webp generator:

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.imageminGenerate,
            options: {
              // Please specify only one plugin here, multiple plugins will not work
              plugins: ["imagemin-webp"],
            },
          },
        ],
      }),
    ],
  },
};

DEPRECATED Generator example for squoosh

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.squooshGenerate,
            options: {
              encodeOptions: {
                // Please specify only one codec here, multiple codecs will not work
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

Generator example for sharp

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              encodeOptions: {
                // Please specify only one codec here, multiple codecs will not work
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

Now you can generate the new image using:

// Old approach for getting URL
import webp from "./file.jpg?as=webp";

// Assets modules
console.log(new URL("./file.jpg?as=webp"));
div {
  background: url("./file.jpg?as=webp");
}

You can use ?as=webp in any type of files.

Example multiple generators:

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              encodeOptions: {
                webp: {
                  lossless: false,
                },
              },
            },
          },
          {
            // You can apply generator using `?as=avif`, you can use any name and provide more options
            preset: "avif",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              encodeOptions: {
                avif: {
                  lossless: false,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

squoosh and sharp generator supports more options, for example you can resize an image:

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp-100-50`, you can use any name and provide more options
            preset: "webp-100-50",
            // implementation: ImageMinimizerPlugin.squooshGenerate,
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              resize: {
                enabled: true,
                width: 100,
                height: 50,
              },
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

You can find more information here.

For only sharp currently, you can even generate the non-retina resizes of images:

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp-1x`, you can use any name and provide more options
            preset: "webp-1x",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              resize: {
                enabled: true,
                width: 50,
                unit: "percent",
              },
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

Generator example for user defined implementation

You can use your own generator implementation.

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: async (original, options) => {
              const inputExt = path.extname(original.filename).toLowerCase();

              if (inputExt !== ".xxx") {
                // Store error and return `null` if the implementation does not support this file type
                original.errors.push(error);
                return null;
              }

              let result;

              try {
                result = await minifyAndReturnBuffer(original.data);
              } catch (error) {
                // Store error and return `null` if there was an error
                original.errors.push(error);
                return null;
              }

              return {
                filename: original.filename,
                data: result,
                warnings: [...original.warnings],
                errors: [...original.errors],
                info: {
                  ...original.info,
                  // Please always set it to prevent double minification
                  generated: true,
                  // Optional
                  generatedBy: ["custom-name-of-minification"],
                },
              };
            },
            options: {
              // Your options
            },
          },
        ],
      }),
    ],
  },
};

Generator options

type

Type:

type type = "import" | "asset" | undefined;

Default: "import"

Allows you to apply the generator for import or assets from compilation (useful for copied assets). By default, generators are applying on import/require, but sometimes you need to generate new images from other plugins (for example - copy-webpack-plugin), if you need this, please set asset value for the type option.

webpack.config.js

const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
        generator: [
          {
            // Apply generator for copied assets
            type: "asset",
            // You can use `ImageMinimizerPlugin.squooshGenerate`
            // You can use `ImageMinimizerPlugin.sharpGenerate`
            implementation: ImageMinimizerPlugin.imageminGenerate,
            options: {
              plugins: ["imagemin-webp"],
            },
          },
        ],
      }),
    ],
  },
  plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
preset

Type:

type preset = string | undefined;

Default: undefined

Configure the name of preset, i.e. you can use it in ?as=name.

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            preset: "name",
            // Implementation
            implementation: ImageMinimizerPlugin.sharpMinify,
            options: {
              encodeOptions: {
                jpeg: {
                  quality: 85,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};
implementation

Type:

type implementation = (
  original: {
    filename: string;
    data: Buffer;
    warnings: Array<Error>;
    errors: Array<Error>;
    info: import("webpack").AssetInfo;
  },
  options?:
    | {
        [key: string]: any;
      }
    | undefined,
) => Promise<{
  filename: string;
  data: Buffer;
  warnings: Array<Error>;
  errors: Array<Error>;
  info: import("webpack").AssetInfo;
}> & {
  setup?: (() => void) | undefined;
  teardown?: (() => void) | undefined;
};

Default: undefined

Configure the default implementation.

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            preset: "name",
            // Implementation
            implementation: ImageMinimizerPlugin.sharpMinify,
            options: {
              encodeOptions: {
                jpeg: {
                  quality: 85,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};
options

Type:

type options = {
  [key: string]: any;
};

Default: undefined

Options for the implementation option (i.e. options for imagemin/squoosh/sharp/custom implementation).

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            preset: "name",
            implementation: ImageMinimizerPlugin.sharpMinify,
            // Options
            options: {
              encodeOptions: {
                jpeg: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};
filter

Type:

type filter = (source: Buffer, sourcePath: string) => boolean;

Default: () => true

Allows filtering of images for optimization/generation.

Return true to optimize the image, false otherwise.

webpack.config.js

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

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

              return true;
            },
            implementation: ImageMinimizerPlugin.imageminMinify,
            options: {
              plugins: [
                "imagemin-gifsicle",
                "imagemin-mozjpeg",
                "imagemin-pngquant",
                "imagemin-svgo",
              ],
            },
          },
        ],
      }),
    ],
  },
};
filename

Type:

type filename =
  | string
  | ((
      pathData: PathData,
      assetInfo?: import("webpack").AssetInfo | undefined,
    ) => string);

Default: undefined

Allows to set the filename. Supported values see in webpack template strings, File-level section.

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            preset: "name",
            filename: "generated-[name][ext]",
            implementation: ImageMinimizerPlugin.sharpMinify,
            // Options
            options: {
              encodeOptions: {
                jpeg: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

Example of function usage:

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        generator: [
          {
            preset: "name",
            filename: () => "generated-[name][ext]",
            implementation: ImageMinimizerPlugin.sharpMinify,
            // Options
            options: {
              encodeOptions: {
                jpeg: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

severityError

Type:

type severityError = string;

Default: 'error'

Allows to choose how errors are displayed.

Сan have the following values:

  • 'off' - suppresses errors and warnings
  • 'warning' - emit warnings instead errors
  • 'error' - emit errors

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        severityError: "warning",
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};

loader

Type:

type loader = boolean;

Default: true

Automatically adding built-in loader, used to optimize/generate images.

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        loader: false,
        // `generator` will not work in this case
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};

concurrency

Type:

type concurrency = number;

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

Maximum number of concurrency optimization processes in one time.

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        concurrency: 3,
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};

deleteOriginalAssets

Type:

type deleteOriginalAssets = boolean;

Default: true

Allows removing original assets after optimization.

Please use this option if you are set the filename option for the minimizer option, disable loader: false and want to keep optimized and not optimized assets.

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        // Disable loader
        loader: false,
        // Allows to keep original asset and minimized assets with different filenames
        deleteOriginalAssets: false,
        minimizer: {
          filename: "[path][name].webp",
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
      }),
    ],
  },
};

Loader Options

minimizer

Type:

type minimizer =
  | {
      implementation: (
        original: {
          filename: string;
          data: Buffer;
          warnings: Array<Error>;
          errors: Array<Error>;
          info: import("webpack").AssetInfo;
        },
        options?:
          | {
              [key: string]: any;
            }
          | undefined,
      ) => Promise<{
        filename: string;
        data: Buffer;
        warnings: Array<Error>;
        errors: Array<Error>;
        info: import("webpack").AssetInfo;
      }> & {
        setup?: (() => void) | undefined;
        teardown?: (() => void) | undefined;
      };
      options?:
        | {
            [key: string]: any;
          }
        | undefined;
      filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
      filename?:
        | string
        | ((
            pathData: {
              filename?: string | undefined;
            },
            assetInfo?: import("webpack").AssetInfo | undefined,
          ) => string)
        | undefined;
    }
  | Array<{
      implementation: (
        original: {
          filename: string;
          data: Buffer;
          warnings: Array<Error>;
          errors: Array<Error>;
          info: import("webpack").AssetInfo;
        },
        options?:
          | {
              [key: string]: any;
            }
          | undefined,
      ) => Promise<{
        filename: string;
        data: Buffer;
        warnings: Array<Error>;
        errors: Array<Error>;
        info: import("webpack").AssetInfo;
      }> & {
        setup?: (() => void) | undefined;
        teardown?: (() => void) | undefined;
      };
      options?:
        | {
            [key: string]: any;
          }
        | undefined;
      filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
      filename?:
        | string
        | ((
            pathData: {
              filename?: string | undefined;
            },
            assetInfo?: import("webpack").AssetInfo | undefined,
          ) => string)
        | undefined;
    }>;

Default: undefined

Allows to setup default minimizer.

Loader minimizer example for imagemin

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: "asset",
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loader: ImageMinimizerPlugin.loader,
        enforce: "pre",
        options: {
          minimizer: {
            implementation: ImageMinimizerPlugin.imageminMinify,
            options: {
              plugins: [
                "imagemin-gifsicle",
                "imagemin-mozjpeg",
                "imagemin-pngquant",
                "imagemin-svgo",
              ],
            },
          },
        },
      },
    ],
  },
};

For more information and supported options please read here.

generator

Type:

type generator = Array<{
  implementation: TransformerFunction<T>;
  options?: BasicTransformerOptions<T>;
  filter?: FilterFn | undefined;
  filename?: string | FilenameFn | undefined;
  preset?: string | undefined;
  type?: "import" | "asset" | undefined;
}>;

Default: undefined

Allow to setup default generators. Useful if you need generate webp/avif/etc from other formats.

Loader generator example for imagemin

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: "asset",
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loader: ImageMinimizerPlugin.loader,
        enforce: "pre",
        options: {
          generator: [
            {
              preset: "webp",
              implementation: ImageMinimizerPlugin.imageminGenerate,
              options: {
                plugins: ["imagemin-webp"],
              },
            },
          ],
        },
      },
    ],
  },
};

For more information and supported options please read here.

severityError

Type:

type severityError = string;

Default: 'error'

Allows to choose how errors are displayed.

Сan have the following values:

  • 'off' - suppresses errors and warnings
  • 'warning' - emit warnings instead errors
  • 'error' - emit 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"],
              },
            },
          },
        ],
      },
    ],
  },
};

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

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

(async () => {
  const imageminConfig = await imageminNormalizeConfig({
    plugins: ["jpegtran", ["pngquant", { quality: [0.6, 0.8] }]],
  });
  const files = await imagemin(["images/*.{jpg,png}"], {
    destination: "build/images",
    plugins: imageminConfig.plugins,
  });

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

Examples

Optimize images based on size

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

What is progressive image? Answer here.

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [["jpegtran", { progressive: true }]],
          },
          // Only apply this one to files equal to or over 8192 bytes
          filter: (source) => {
            if (source.byteLength >= 8192) {
              return true;
            }

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

            return false;
          },
        },
      }),
    ],
  },
};

Optimize and generate webp images

  • imagemin

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.imageminGenerate,
            options: {
              plugins: ["imagemin-webp"],
            },
          },
        ],
      }),
    ],
  },
};
  • DEPRECATED squoosh

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.squooshMinify,
        },
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.squooshGenerate,
            options: {
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};
  • sharp

webpack.config.js

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

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.sharpMinify,
        },
        generator: [
          {
            // You can apply generator using `?as=webp`, you can use any name and provide more options
            preset: "webp",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
};

Generate webp images from copied assets

  • imagemin

webpack.config.js

const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              "imagemin-gifsicle",
              "imagemin-mozjpeg",
              "imagemin-pngquant",
              "imagemin-svgo",
            ],
          },
        },
        generator: [
          {
            type: "asset",
            implementation: ImageMinimizerPlugin.imageminGenerate,
            options: {
              plugins: ["imagemin-webp"],
            },
          },
        ],
      }),
    ],
  },
  plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
  • DEPRECATED squoosh

webpack.config.js

const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.squooshMinify,
        },
        generator: [
          {
            type: "asset",
            implementation: ImageMinimizerPlugin.squooshGenerate,
            options: {
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
  plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
  • sharp

webpack.config.js

const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      "...",
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.sharpMinify,
        },
        generator: [
          {
            type: "asset",
            implementation: ImageMinimizerPlugin.sharpGenerate,
            options: {
              encodeOptions: {
                webp: {
                  quality: 90,
                },
              },
            },
          },
        ],
      }),
    ],
  },
  plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};

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

Internal webpack plugins

Webpack 내부적으로 사용하는 플러그인의 목록입니다.

내부 플러그인의 범주:

environment

컴파일러의 환경에 영향을 주는 플러그인입니다.

NodeEnvironmentPlugin

webpack.node.NodeEnvironmentPlugin()

컴파일러에 Node.js 스타일의 파일 시스템을 적용합니다.

compiler

컴파일러에 영향을 주는 플러그인입니다.

MemoryCachePlugin

MemoryCachePlugin()

모듈이 메모리에 캐시되는 컴파일러에 캐시를 추가합니다.

ProgressPlugin

ProgressPlugin(handler)

컴파일러에 훅을 하여 진행 정보를 추출합니다. handlerfunction(percentage, message)라는 서명이 있어야 합니다. Percentage는 0과 1 사이의 값으로 불립니다. 0은 시작, 1은 끝을 나타냅니다.

RecordIdsPlugin

RecordIdsPlugin()

레코드로부터 청크 아이디와 모듈을 저장하고 복원합니다.

entry

컴파일에 엔트리 청크를 포함하는 플러그인입니다.

EntryPlugin

EntryPlugin(context, entry, options)

컴파일에 엔트리 청크를 추가합니다. 청크의 이름은 options.name이고 오직 하나의 모듈만 포함합니다(의존성 추가). 모듈은 context (절대 경로)의 entry에서 확인됩니다.

PrefetchPlugin

PrefetchPlugin(context, request)

병렬 컴파일을 더 사용하기 위해서 의존성과 request를 프리페치합니다. 어떤 청크도 생성되지 않습니다. 모듈은 context (절대 경로)의 request에서 확인됩니다.

output

JsonpTemplatePlugin

JsonpTemplatePlugin(options)

청크는 JSONP-calls로 래핑되어 있습니다. 로딩 알고리즘은 엔트리 청크에 포함이 됩니다. <script> 태그를 추가함으로써 청크를 로드합니다.

options는 출력 옵션입니다.

options.jsonpFunction은 JSONP 함수입니다.

options.publicPath는 청크를 로딩하기 위한 경로로 사용됩니다.

options.chunkFilename는 청크가 예상되는 파일 이름 이름입니다.

NodeTemplatePlugin

node/NodeTemplatePlugin(options)

청크는 번들 모듈을 내보내는 Node.js 모듈로 래핑되어 있습니다. 엔트리 청크는 청크를 요구함으로써 로드됩니다.

options는 출력 옵션입니다.

options.chunkFilename는 청크를 로딩하기 위한 경로로 사용됩니다.

LibraryTemplatePlugin

LibraryTemplatePlugin(name, target)

엔트리 청크들은 type 유형의 name 라이브러리로부터 꾸며집니다.

WebWorkerTemplatePlugin

webworker/WebWorkerTemplatePlugin(options)

청크는 importScripts에 의해 로드됩니다. 그렇지 않다면 JsonpTemplatePlugin과 비슷합니다.

options은 출력 옵션입니다.

EvalDevToolModulePlugin

// @sourceURL로 주석이 달린 eval로 각각의 모듈을 래핑함으로써 모듈 템플릿을 꾸밉니다.

SourceMapDevToolPlugin

SourceMapDevToolPlugin(sourceMapFilename, sourceMappingURLComment, moduleFilenameTemplate, fallbackModuleFilenameTemplate)

각 청크에 대한 소스맵을 생성함으로써 템플릿들을 꾸밉니다.

sourceMapFilename은 소스맵의 파일 이름 템플릿입니다. [hash], [name], [id], [file][filebase]는 교체되었습니다. 만약에 인자가 없으면, 소스맵은 DataUrl로 인라인 될 것입니다.

HotModuleReplacementPlugin

HotModuleReplacementPlugin(options)

Hot module replacement 대한 지원을 추가합니다. 런타임 코드를 추가한 템플릿을 꾸밉니다. `module.hot' API를 추가합니다.

options.hotUpdateChunkFilename은 hot 업데이트 청크 파일 이름입니다.

options.hotUpdateMainFilename은 hot 업데이트 매니페스트 파일 이름입니다.

options.hotUpdateFunction는 hot 업데이트의 JSON 함수 이름입니다.

source

모듈의 소스 코드에 영향을 미치는 플러그인입니다.

APIPlugin

webpack_public_path, webpack_require, webpack_modules 과 webpack_chunk_load에 접근할 수 있도록 설정합니다. require.valueOfrequire.onError가 다른 플러그인으로 처리되지 않도록 합니다.

CompatibilityPlugin

현재는 쓸모가 없습니다. 다른 모듈 로더과의 호환성을 보장합니다.

ConstPlugin

파서에 의해 발사된 훅을 사용함으로써 dead branch를 추가로 제거를 가능하게 하려고 if (...)문과 삼항 연산자를 평가하여 true/false로 바꾸려고 시도합니다.

프로덕션 모드에는 dead branch와 관련하여 여러 최적화 들이 있습니다.

  • Terser 이 수행한 최적화입니다.
  • Webpack이 수행한 최적화 입니다.

Webpack은 조건문을 평가하려고 할 것입니다. 만약 성공한다면 dead branch가 제거됩니다. Webpck은 컴파일러가 알지 못하는 한 상수 폴딩을 할 수 없습니다. 다음 예시를 봅시다.

import { calculateTax } from './tax';

const FOO = 1;
if (FOO === 0) {
  // dead branch
  calculateTax();
}

위의 예시에서, webpack은 branch를 자를 수 없지만, Terser는 할 수 있습니다. 그러나 만약 FOODefinePlugin 을 사용하면, webpack은 성공할 것입니다.

import { calculateTax } from './tax';도 제거된다는 점을 언급해야 합니다. 왜냐하면 calculateTax() 호출이 dead branch에 있어 제거되었기 때문입니다.

ProvidePlugin

ProvidePlugin(name, request)

만약에 모듈에서 name이 사용되는 경우는 require(<request>)에 의해 로드된 모듈에 의해서 채워집니다.

NodeStuffPlugin

NodeStuffPlugin(options, context)

Node.js 모듈에서는 일반적으로 사용할 수 있는 항목을 제공합니다.

또한, module을 사용하는 경우에는 일부의 Node.js 항목으로 채워지도록 합니다.

RequireJsStuffPlugin

require.js에서는 일반적으로 사용할 수 있는 항목을 제공합니다.

require[js].config는 제거됩니다. require.version0.0.0입니다. requirejs.onErrorrequire.onError에 매핑이 됩니다.

NodeSourcePlugin

node/NodeSourcePlugin(options)

이 모듈은 Node.js 환경이 아니면 사용할 수 없는 Node.js의 내용을 추가합니다.

사용되는 경우에는 process, console, Bufferglo에 대한 polyfills을 추가해야 합니다.

NodeTargetPlugin

node/NodeTargetPlugin()

만약 Node.js 환경에서 번들을 실행하는 경우에는 플러그인을 사용해야 합니다.

만약 네이티브 모듈이 번들 되어있더라도 올바르게 로드되도록 보장합니다.

AMDPlugin

dependencies/AMDPlugin(options)

AMD 스타일의 definerequire 모듈을 제공합니다. 또한, require.amd, define.amd 와 webpack_amd_options## 를 파라미터로 전달된 options에 바인딩합니다.

CommonJsPlugin

dependencies/CommonJsPlugin

CommonJs 스타일의 require 모듈을 제공합니다.

RequireContextPlugin

dependencies/RequireContextPlugin(modulesDirectories, extensions)

require.content를 제공합니다. modulesDirectoriesextensions 파라미터는 파일에 대한 요청을 대체할 수 있는 것을 찾는 데 사용됩니다. 리졸버에 제공하는 것과 동일한 배열을 제공하는 것이 유용합니다.

RequireEnsurePlugin

dependencies/RequireEnsurePlugin()

require.ensure를 제공합니다.

RequireIncludePlugin

dependencies/RequireIncludePlugin()

require.include를 제공합니다.

DefinePlugin

DefinePlugin(definitions)

식별자에 대해 상수를 정의합니다.

definitions은 객체입니다.

optimize

webpack.optimize 네임스페이스 아래의 모든 플러그인은 mode'none'으로 설정된 경우에만 사용해야 합니다. 그렇지 않다면 플러그인은 두 번 적용되어야 합니다.

LimitChunkCountPlugin

optimize/LimitChunkCountPlugin(options)

병합 청크의 제한된 청크 수는 `options.maxChunks'보다 작습니다.

각 청크에 대한 오버헤드는 options.chunkOverhead 또는 기본값인 10000에 의해 제공됩니다. 엔트리 청크의 크기는 options.entryChunkMultiplicator (또는 10)에 의해 곱해집니다.

전체적인 크기를 가장 많이 줄인 청크가 첫 번째로 병합됩니다. 만약 여러 조합이 같으면 병합된 크기가 작은 것이 선택됩니다.

MergeDuplicateChunksPlugin

optimize/MergeDuplicateChunksPlugin()

같은 모듈의 청크가 병합됩니다.

RemoveEmptyChunksPlugin

optimize/RemoveEmptyChunksPlugin()

모든 부모 청크에 포함된 모듈은 청크로부터 제거됩니다.

MinChunkSizePlugin

optimize/MinChunkSizePlugin(minChunkSize)-

각 청크의 최소 크기가 minChunkSize가 될 때까지 청크를 병합합니다.

ModuleConcatenationPlugin

ModuleConcatenationPlugin page에 대한 구체적인 내용을 확인해보세요.

FlagIncludedChunksPlugin

optimize/FlagIncludedChunksPlugin()

청크에 포함된 청크의 청크 아이디를 추가합니다. 불필요한 청크 로드를 제거할 수 있습니다.

RealContentHashPlugin

optimize/RealContentHashPlugin()

optimization.realContentHash 옵션이 활성화 될 때, webpack은 내부적으로 RealContentHashPlugin을 컴파일러에 추가합니다.

Hook

RealContentHashPlugin은 해시 업데이트를 커스터마이징할 수 있는 훅인 updateHash 5.8.0+를 제공합니다.

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) => {
    // 이곳에서 원하는데로 해시를 계산할 수 있습니다.
  });
});

JsonMinimizerWebpackPlugin

npm node tests cover discussion 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

or

yarn add -D json-minimizer-webpack-plugin

or

pnpm add -D json-minimizer-webpack-plugin

Then add the plugin to your webpack configuration. For example:

webpack.config.js

const JsonMinimizerPlugin = require("json-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.json$/i,
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          context: path.resolve(__dirname, "dist"),
          from: "./src/*.json",
        },
      ],
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
      // `...`
      new JsonMinimizerPlugin(),
    ],
  },
};

And run webpack via your preferred method.

Options

test

Type:

type test = string | RegExp | Array<string | RegExp>;

Default: /\.json(\?.*)?$/i

Test to match files against.

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

include

Type:

type include = string | RegExp | Array<string | RegExp>;

Default: undefined

Files to include.

webpack.config.js

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

exclude

Type:

type exclude = string | RegExp | Array<string | RegExp>;

Default: undefined

Files to exclude.

webpack.config.js

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

minimizerOptions

Type:

type minimizerOptions = {
  space?: null | string | number;
  replacer?: null | Function | Array<string | number>;
};

Default: { replacer: null, space: null }

JSON.stringify() options.

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

Contributing

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

CONTRIBUTING

License

MIT

LimitChunkCountPlugin

코드를 작성할 때, 이미 필요한 것을 로드할 많은 코드 분할 지점을 추가했을 것입니다. 컴파일 후에 어떤 청크가 너무 작다는 것을 깨달을 것입니다. 이는 더 큰 HTTP 오버헤드를 만듭니다. LimitChunkCountPlugin은 청크를 합침으로써 그것들을 후속 처리할 수 있게 해줍니다.

new webpack.optimize.LimitChunkCountPlugin({
  // Options...
});

Options

다음의 옵션들이 지원됩니다.

maxChunks

number

청크의 최대 개수를 1보다 크거나 같도록 제한합니다. 1을 사용하는 것은 엔트리/메인 청크가 카운트에 포함될 때 추가적인 청크가 더해지는 것을 방지합니다.

webpack.config.js

const webpack = require('webpack');
module.exports = {
  // ...
  plugins: [
    new webpack.optimize.LimitChunkCountPlugin({
      maxChunks: 5,
    }),
  ],
};

minChunkSize

위의 지정된 청크 크기를 유지하는 것은 이 플러그인에서 구현하지 않습니다. MinChunkSizePlugin을 대신 사용하세요.

Usage via CLI

이 플러그인과 옵션은 CLI를 통해 호출될 수도 있습니다.

webpack --optimize-max-chunks 15

MinChunkSizePlugin

minChunkSize보다 작은 청크를 병합하여 청크 크기를 설정한 한계 이상으로 유지합니다.

new webpack.optimize.MinChunkSizePlugin({
  minChunkSize: 10000, // 최소 문자 수
});

Usage via CLI

해당 플러그인과 플러그인 옵션은 CLI를 통해서도 실행할 수 있습니다.

webpack --optimize-min-chunk-size 10000

MiniCssExtractPlugin

npm node tests coverage discussion size

This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps.

It builds on top of a new webpack v5 feature and requires webpack 5 to work.

Compared to the extract-text-webpack-plugin:

  • Async loading
  • No duplicate compilation (performance)
  • Easier to use
  • Specific to CSS

Getting Started

To begin, you'll need to install mini-css-extract-plugin:

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

or

yarn add -D mini-css-extract-plugin

or

pnpm add -D mini-css-extract-plugin

It's recommended to combine mini-css-extract-plugin with the css-loader

Then add the loader and the plugin to your webpack config. For example:

style.css

body {
  background: green;
}

component.js

import "./style.css";

webpack.config.js

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

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

[!WARNING]

Note that if you import CSS from your webpack entrypoint or import styles in the initial chunk, mini-css-extract-plugin will not load this CSS into the page. Please use html-webpack-plugin for automatic generation link tags or create index.html file with link tag.

[!WARNING]

Source maps works only for source-map/nosources-source-map/hidden-nosources-source-map/hidden-source-map values because CSS only supports source maps with the sourceMappingURL comment (i.e. //# sourceMappingURL=style.css.map). If you need set devtool to another value you can enable source maps generation for extracted CSS using sourceMap: true for css-loader.

Options

Plugin Options

filename

Type:

type filename =
  | string
  | ((pathData: PathData, assetInfo?: AssetInfo) => string);

Default: [name].css

This option determines the name of each output CSS file.

Works like output.filename

chunkFilename

Type:

type chunkFilename =
  | string
  | ((pathData: PathData, assetInfo?: AssetInfo) => string);

Default: based on filename

Specifying chunkFilename as a function is only available in webpack@5

This option determines the name of non-entry chunk files.

Works like output.chunkFilename

ignoreOrder

Type:

type ignoreOrder = boolean;

Default: false

Remove Order Warnings. See examples below for details.

insert

Type:

type insert = string | ((linkTag: HTMLLinkElement) => void);

Default: document.head.appendChild(linkTag);

Inserts the link tag at the given position for non-initial (async) CSS chunks

[!WARNING]

Only for non-initial (async) chunks.

By default, the mini-css-extract-plugin appends styles (<link> elements) to document.head of the current window.

However in some circumstances it might be necessary to have finer control over the append target or even delay link elements insertion. For example this is the case when you asynchronously load styles for an application that runs inside of an iframe. In such cases insert can be configured to be a function or a custom selector.

If you target an iframe make sure that the parent document has sufficient access rights to reach into the frame document and append elements to it.

string

Allows to setup custom query selector. A new <link> element will be inserted after the found item.

webpack.config.js

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

A new <link> element will be inserted after the element with id some-element.

function

Allows to override default behavior and insert styles at any position.

⚠ Do not forget that this code will run in the browser alongside your application. Since not all browsers support latest ECMA features like let, const, arrow function expression and etc we recommend you to use only ECMA 5 features and syntax.

⚠ The insert function is serialized to string and passed to the plugin. This means that it won't have access to the scope of the webpack configuration module.

webpack.config.js

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

A new <link> element will be inserted before the element with id some-element.

attributes

Type:

type attributes = Record<string, string>};

Default: {}

[!WARNING]

Only for non-initial (async) chunks.

If defined, the mini-css-extract-plugin will attach given attributes with their values on <link> element.

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      attributes: {
        id: "target",
        "data-target": "example",
      },
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

[!NOTE]

It's only applied to dynamically loaded css chunks, if you want to modify link attributes inside html file, please using html-webpack-plugin

linkType

Type:

type linkType = string | boolean;

Default: text/css

This option allows loading asynchronous chunks with a custom link type, such as <link type="text/css" ...>.

string

Possible values: text/css

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      linkType: "text/css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};
boolean

false disables the link type attribute

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      linkType: false,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

runtime

Type:

type runtime = boolean;

Default: true

Allows to enable/disable the runtime generation. CSS will be still extracted and can be used for a custom loading methods. For example, you can use assets-webpack-plugin to retrieve them then use your own runtime code to download assets when needed.

false to skip.

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      runtime: false,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

experimentalUseImportModule

Type:

type experimentalUseImportModule = boolean;

Default: undefined

Enabled by default if not explicitly enabled (i.e. true and false allow you to explicitly control this option) and new API is available (at least webpack 5.52.0 is required). Boolean values are available since version 5.33.2, but you need to enable experiments.executeModule (not required from webpack 5.52.0).

Use a new webpack API to execute modules instead of child compilers. This improves performance and memory usage a lot.

When combined with experiments.layers, this adds a layer option to the loader options to specify the layer of the css execution.

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // You don't need this for `>= 5.52.0` due to the fact that this is enabled by default
      // Required only for `>= 5.33.2 & <= 5.52.0`
      // Not available/unsafe for `<= 5.33.2`
      experimentalUseImportModule: true,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Loader Options

publicPath

Type:

type publicPath =
  | string
  | ((resourcePath: string, rootContext: string) => string);

Default: the publicPath in webpackOptions.output

Specifies a custom public path for the external resources like images, files, etc inside CSS. Works like output.publicPath

string

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: "/public/path/to/",
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};
function

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: (resourcePath, context) => {
                return path.relative(path.dirname(resourcePath), context) + "/";
              },
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

emit

Type:

type emit = boolean;

Default: true

If true, emits a file (writes a file to the filesystem). If false, the plugin will extract the CSS but will not emit the file. It is often useful to disable this option for server-side packages.

esModule

Type:

type esModule = boolean;

Default: true

By default, mini-css-extract-plugin generates JS modules that use the ES modules syntax. There are some cases in which using ES modules is beneficial, like in the case of module concatenation and tree shaking.

You can enable a CommonJS syntax using:

webpack.config.js

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

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              esModule: false,
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

defaultExport

Type:

type defaultExport = boolean;

Default: false

[!NOTE]

This option will work only when you set namedExport to true in css-loader

By default, mini-css-extract-plugin generates JS modules based on the esModule and namedExport options in css-loader. Using the esModule and namedExport options will allow you to better optimize your code. If you set esModule: true and namedExport: true for css-loader mini-css-extract-plugin will generate only a named export. Our official recommendation is to use only named export for better future compatibility. But for some applications, it is not easy to quickly rewrite the code from the default export to a named export.

In case you need both default and named exports, you can enable this option:

webpack.config.js

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

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              defaultExport: true,
            },
          },
          {
            loader: "css-loader",
            options: {
              esModule: true,
              modules: {
                namedExport: true,
              },
            },
          },
        ],
      },
    ],
  },
};

Examples

Recommended

For production builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on. This can be achieved by using the mini-css-extract-plugin, because it creates separate css files. For development mode (including webpack-dev-server) you can use style-loader, because it injects CSS into the DOM using multiple and works faster.

Do not use style-loader and mini-css-extract-plugin together.

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      {
        // If you enable `experiments.css` or `experiments.futureDefaults`, please uncomment line below
        // type: "javascript/auto",
        test: /\.(sa|sc|c)ss$/,
        use: [
          devMode ? "style-loader" : MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      },
    ],
  },
  plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};

Minimal example

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

⚠ Names of locals are converted to camelCase.

⚠ It is not allowed to use JavaScript reserved words in css class names.

⚠ Options esModule and modules.namedExport in css-loader should be enabled.

styles.css

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

index.js

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

console.log(fooBaz, bar);

You can enable a ES module named export using:

webpack.config.js

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

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
          },
          {
            loader: "css-loader",
            options: {
              esModule: true,
              modules: {
                namedExport: true,
                localIdentName: "foo__[name]__[local]",
              },
            },
          },
        ],
      },
    ],
  },
};

The publicPath option as function

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: (resourcePath, context) => {
                // publicPath is the relative path of the resource to the context
                // e.g. for ./css/admin/main.css the publicPath will be ../../
                // while for ./css/main.css the publicPath will be ../
                return path.relative(path.dirname(resourcePath), context) + "/";
              },
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

Advanced configuration example

This plugin should not be used with style-loader in the loaders chain.

Here is an example to have both HMR in development and your styles extracted in a file for production builds.

(Loaders options left out for clarity, adapt accordingly to your needs.)

You should not use HotModuleReplacementPlugin plugin if you are using a webpack-dev-server. webpack-dev-server enables / disables HMR using hot option.

webpack.config.js

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

const plugins = [
  new MiniCssExtractPlugin({
    // Options similar to the same options in webpackOptions.output
    // both options are optional
    filename: devMode ? "[name].css" : "[name].[contenthash].css",
    chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
  }),
];
if (devMode) {
  // only enable hot in development
  plugins.push(new webpack.HotModuleReplacementPlugin());
}

module.exports = {
  plugins,
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      },
    ],
  },
};

Hot Module Reloading (HMR)

[!NOTE]

HMR is automatically supported in webpack 5. No need to configure it. Skip the following:

The mini-css-extract-plugin supports hot reloading of actual css files in development. Some options are provided to enable HMR of both standard stylesheets and locally scoped CSS or CSS modules. Below is an example configuration of mini-css for HMR use with CSS modules.

You should not use HotModuleReplacementPlugin plugin if you are using a webpack-dev-server. webpack-dev-server enables / disables HMR using hot option.

webpack.config.js

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

const plugins = [
  new MiniCssExtractPlugin({
    // Options similar to the same options in webpackOptions.output
    // both options are optional
    filename: devMode ? "[name].css" : "[name].[contenthash].css",
    chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
  }),
];
if (devMode) {
  // only enable hot in development
  plugins.push(new webpack.HotModuleReplacementPlugin());
}

module.exports = {
  plugins,
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {},
          },
          "css-loader",
        ],
      },
    ],
  },
};

Minimizing For Production

To minify the output, use a plugin like css-minimizer-webpack-plugin.

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
  optimization: {
    minimizer: [
      // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
      // `...`,
      new CssMinimizerPlugin(),
    ],
  },
};

This will enable CSS optimization only in production mode. If you want to run it also in development set the optimization.minimize option to true.

Using preloaded or inlined CSS

The runtime code detects already added CSS via <link> or <style> tag. This can be useful when injecting CSS on server-side for Server-Side-Rendering. The href of the <link> tag has to match the URL that will be used for loading the CSS chunk. The data-href attribute can be used for <link> and <style> too. When inlining CSS data-href must be used.

Extracting all CSS in a single file

The CSS can be extracted in one CSS file using optimization.splitChunks.cacheGroups.

webpack.config.js

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

module.exports = {
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: "styles",
          type: "css/mini-extract",
          chunks: "all",
          enforce: true,
        },
      },
    },
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Note that type should be used instead of test in Webpack 5, or else an extra .js file can be generated besides the .css file. This is because test doesn't know which modules should be dropped (in this case, it won't detect that .js should be dropped).

Extracting CSS based on entry

You may also extract the CSS based on the webpack entry name. This is especially useful if you import routes dynamically but want to keep your CSS bundled according to entry. This also prevents the CSS duplication issue one had with the ExtractTextPlugin.

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

module.exports = {
  entry: {
    foo: path.resolve(__dirname, "src/foo"),
    bar: path.resolve(__dirname, "src/bar"),
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        fooStyles: {
          type: "css/mini-extract",
          name: "styles_foo",
          chunks: (chunk) => {
            return chunk.name === "foo";
          },
          enforce: true,
        },
        barStyles: {
          type: "css/mini-extract",
          name: "styles_bar",
          chunks: (chunk) => {
            return chunk.name === "bar";
          },
          enforce: true,
        },
      },
    },
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Filename Option as function

With the filename option you can use chunk data to customize the filename. This is particularly useful when dealing with multiple entry points and wanting to get more control out of the filename for a given entry point/chunk. In the example below, we'll use filename to output the generated css into a different directory.

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: ({ chunk }) => `${chunk.name.replace("/js/", "/css/")}.css`,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Long Term Caching

For long term caching use filename: "[contenthash].css". Optionally add [name].

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].[contenthash].css",
      chunkFilename: "[id].[contenthash].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Remove Order Warnings

For projects where css ordering has been mitigated through consistent use of scoping or naming conventions, such as CSS Modules, the css order warnings can be disabled by setting the ignoreOrder flag to true for the plugin.

webpack.config.js

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      ignoreOrder: true,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Multiple Themes

webpack.config.js

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

module.exports = {
  entry: "./src/index.js",
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        oneOf: [
          {
            resourceQuery: "?dark",
            use: [
              MiniCssExtractPlugin.loader,
              "css-loader",
              {
                loader: "sass-loader",
                options: {
                  additionalData: `@use 'dark-theme/vars' as vars;`,
                },
              },
            ],
          },
          {
            use: [
              MiniCssExtractPlugin.loader,
              "css-loader",
              {
                loader: "sass-loader",
                options: {
                  additionalData: `@use 'light-theme/vars' as vars;`,
                },
              },
            ],
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      attributes: {
        id: "theme",
      },
    }),
  ],
};

src/index.js

import "./style.scss";

let theme = "light";
const themes = {};

themes[theme] = document.querySelector("#theme");

async function loadTheme(newTheme) {
  // eslint-disable-next-line no-console
  console.log(`CHANGE THEME - ${newTheme}`);

  const themeElement = document.querySelector("#theme");

  if (themeElement) {
    themeElement.remove();
  }

  if (themes[newTheme]) {
    // eslint-disable-next-line no-console
    console.log(`THEME ALREADY LOADED - ${newTheme}`);

    document.head.appendChild(themes[newTheme]);

    return;
  }

  if (newTheme === "dark") {
    // eslint-disable-next-line no-console
    console.log(`LOADING THEME - ${newTheme}`);

    import(/* webpackChunkName: "dark" */ "./style.scss?dark").then(() => {
      themes[newTheme] = document.querySelector("#theme");

      // eslint-disable-next-line no-console
      console.log(`LOADED - ${newTheme}`);
    });
  }
}

document.onclick = () => {
  if (theme === "light") {
    theme = "dark";
  } else {
    theme = "light";
  }

  loadTheme(theme);
};

src/dark-theme/_vars.scss

$background: black;

src/light-theme/_vars.scss

$background: white;

src/styles.scss

body {
  background-color: vars.$background;
}

public/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Document</title>
    <link id="theme" rel="stylesheet" type="text/css" href="./main.css" />
  </head>
  <body>
    <script src="./main.js"></script>
  </body>
</html>

Media Query Plugin

If you'd like to extract the media queries from the extracted CSS (so mobile users don't need to load desktop or tablet specific CSS anymore) you should use one of the following plugins:

Hooks

The mini-css-extract-plugin provides hooks to extend it to your needs.

beforeTagInsert

SyncWaterfallHook

Called before inject the insert code for link tag. Should return a string

MiniCssExtractPlugin.getCompilationHooks(compilation).beforeTagInsert.tap(
  "changeHref",
  (source, varNames) =>
    Template.asString([
      source,
      `${varNames.tag}.setAttribute("href", "/plugins/mini-css-extract-plugin/));`,
    ])
);

Contributing

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

CONTRIBUTING

License

MIT

ModuleConcatenationPlugin

과거에 번들링을 할 때 webpack의 절충점 중 하나는 번들의 각 모듈이 개별 함수 클로저에 의해 래핑된다는 점이었습니다. 이러한 래퍼 함수는 브라우저에서 자바스크립트의 실행을 느리게 만들었습니다. 이와 달리, Closure Comiler와 RollupJS와 같은 도구는 모든 모듈을 하나의 클로저로 호이스팅 하거나 연결하여 코드가 브라우저에서 더 빠른 실행 시간을 갖게 했습니다.

이 플러그인은 위의 내용과 같은 연결 동작이 webpack에서 가능하게 해줍니다. 기본적으로 이 플러그인은 production mode에서는 이미 가능하고 나머지에서는 아직 가능하지 않습니다. 만약 생산 mode 최적화를 무효로 해야 하는 경우, optimization.concatenateModules 옵션false로 설정하세요. 다른 모드에서 연결 동작을 가능하게 하고 싶을 경우, ModuleConcatenationPlugin을 수동으로 설정하거나 optimization.concatenateModules 옵션을 사용하세요.

new webpack.optimize.ModuleConcatenationPlugin();

이 연결 동작은 “범위 호이스팅” 이라고 불립니다.

범위 호이스팅은 특별히 ECMAScript Module 문법에서 사용 가능하도록 만들어진 형태입니다. 이로 인해 webpack은 현재 사용 중인 모듈의 종류와 다른 여러 조건에 따라 평범한 번들링으로 퇴화할 수도 있습니다.

Optimization Bailouts

글에서 설명하듯이 webpack은 부분적인 범위 호이스팅을 시도합니다. 이는 모듈을 하나의 범위로 합치지만 모든 경우에 합치지는 못합니다. 만약 webapck이 모듈을 합칠 수 없다면 두 가지 대안은 Prevent와 Root 입니다. Prevent는 모듈이 반드시 그 자신의 범위 안에 있어야 한다는 것을 의미합니다. Root는 새로운 모듈 그룹이 생성될 것이라는 의미입니다. 다음의 조건이 결과를 결정합니다.

ConditionOutcome
Non ES6 ModulePrevent
Non Import로 가져옴Root
다른 청크에서 가져옴Root
다수의 다른 모듈 그룹에서 가져옴Root
import()로 가져옴Root
ProvidePlugin의 영향을 받거나 module 사용Prevent
HMR 허용Root
eval() 사용Prevent
다수의 청크Prevent
"cjs-module"로부터 * 내보내기Prevent

Module Grouping Algorithm

아래의 자바스크립트 의사코드는 이 알고리즘을 설명합니다.

modules.forEach((module) => {
  const group = new ModuleGroup({
    root: module,
  });
  module.dependencies.forEach((dependency) => {
    tryToAdd(group, dependency);
  });
  if (group.modules.length > 1) {
    orderedModules = topologicalSort(group.modules);
    concatenatedModule = new ConcatenatedModule(orderedModules);
    chunk.add(concatenatedModule);
    orderedModules.forEach((groupModule) => {
      chunk.remove(groupModule);
    });
  }
});

function tryToAdd(group, module) {
  if (group.has(module)) {
    return true;
  }
  if (!hasPreconditions(module)) {
    return false;
  }
  const nextGroup = group;
  const result = module.dependents.reduce((check, dependent) => {
    return check && tryToAdd(nextGroup, dependent);
  }, true);
  if (!result) {
    return false;
  }
  module.dependencies.forEach((dependency) => {
    tryToAdd(group, dependency);
  });
  group.merge(nextGroup);
  return true;
}

Debugging Optimization Bailouts

webpack CLI를 사용할 경우 --stats-optimization-bailout 플래그는 bailout 원인을 보여줍니다. webpack config를 사용할 경우 stats 객체에 다음을 추가하세요.

module.exports = {
  //...
  stats: {
    // Display bailout reasons
    optimizationBailout: true,
  },
};

Plugins

Webpack에는 많은 플러그인 인터페이스가 있습니다. Webpack 자체에 있는 대부분의 기능은 플러그인 인터페이스를 사용합니다. 이런점이 webpack을 유연하게 만듭니다.

이름설명
BannerPlugin생성된 청크의 상단에 배너 추가
ChunksWebpackPlugin번들을 제공하기 위해 엔트리 포인트 및 청크 관계가 포함된 HTML 파일 생성
CommonsChunkPlugin청크 간에 공유되는 공통 모듈 추출
CompressionWebpackPluginContent-Encoding으로 제공할 압축된 버전의 애셋 준비
ContextReplacementPluginrequire 표현식의 유추된 컨텍스트 재정의
CopyWebpackPlugin개별 파일 또는 전체 디렉터리를 빌드 디렉터리에 복사
DefinePlugin컴파일 타임에 전역 변수 선언
DllPlugin빌드 시간을 단축시키기 위해 번들 분할
EnvironmentPluginprocess.env 키에서 DefinePlugin을 사용하는 약어
EslintWebpackPluginwebpack을 위한 ESLint 플러그인
HotModuleReplacementPluginHot Module Replacement (HMR) 활성화
HtmlWebpackPlugin번들을 제공하기 위한 HTML 파일을 쉽게 생성
IgnorePlugin번들에서 특정 모듈 제외
LimitChunkCountPlugin청킹을 더 잘 제어하기 위한 청킹의 최소/최대 제한 설정
MinChunkSizePlugin청크 크기를 지정한 제한 이상으로 유지
MiniCssExtractPluginCSS파일을 필요로하는 JS파일만 CSS파일을 생성
NoEmitOnErrorsPlugin컴파일 오류가 있는 경우 방출 단계를 건너뜀
NormalModuleReplacementPlugin정규식과 일치하는 리소스 교체
NpmInstallWebpackPlugin개발단계에서 누락된 디펜던시 자동 설치
ProgressPlugin컴파일 진행률 보고
ProvidePluginimport 또는 require 사용없이 모듈 사용
SourceMapDevToolPlugin소스맵을 세밀하게 제어
EvalSourceMapDevToolPlugineval 소스맵을 세밀하게 제어
SvgChunkWebpackPlugin엔트리 포인트의 의존성을 기반으로 SVGO에 의해 최적화된 SVG 스프라이트 생성
TerserPluginTerser를 사용하여 JS 압축

더 많은 써드 파티 플러그인을 찾고 싶다면, awesome-webpack을 참고하세요.

ModuleFederationPlugin

ModuleFederationPlugin을 사용하면 런타임에 다른 독립 빌드와 함께 모듈을 제공하거나 사용할 수 있습니다.

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // 여러 옵션을 타입스크립트로 작성합니다.
      runtime: string | false,
    }),
  ],
};

Options

runtime

특정한 이름으로 새로운 런타임 청크를 만듭니다.

webpack.config.js

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      runtime: 'my-runtime-name',
    }),
  ],
};

Sharing libraries

설정의 'shared' 키를 사용하면 모듈 연합 사이에 공유되는 라이브러리를 정의할 수 있습니다. 패키지 이름은 package.json의 'dependencies' 섹션에 있는 이름과 동일합니다. 그러나 기본적으로 webpack은 라이브러리의 루트 레벨만 공유합니다.

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // date-fns를 공유 모듈로 추가합니다.
      shared: ['date-fns'],
    }),
  ],
};

따라서 응용 프로그램에서 다음과 같은 작업을 수행할 수 있습니다.

import { format } from 'date-fns';

format(new Date(2014, 1, 11), 'MM/dd/yyyy');

그리고 webpack은 date-fns를 공유 라이브러리로 정의하는 모든 모듈 연합 사이에 date-fns를 자동으로 공유합니다. 그러나 패키지의 루트 레벨에 없는 항목(예: date-fns/locale/en-GB/index.js)에 액세스하려면 '공유' 설정에서 패키지 이름에 /를 추가해야 합니다.

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // date-fns를 공유 모듈로 추가합니다.
      // 패키지의 모든 파일이 공유됩니다
      shared: ['date-fns/'],
    }),
  ],
};

The / 구문을 사용하면 패키지의 모든 파일에 액세스할 수 있습니다. 그러나 특히 개발 모드에서는 성능에 영향을 미치므로 필요한 경우에만 사용해야 합니다.

Specify package versions

공유 라이브러리의 버전을 지정하는 세 가지 방법이 있습니다.

Array syntax

이 구문을 사용하면 패키지 이름만 있는 라이브러리를 공유할 수 있습니다. 이 접근 방식은 프로토타이핑에 적합하지만 reactreact-dom과 같은 라이브러리에 추가 요구 사항이 필요하기 때문에 대규모 프로덕션 환경으로 확장할 수 없습니다.

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // lodash를 공유 모듈로 추가합니다.
      // package.json으로부터 버전을 추론합니다.
      // 필수 버전을 확인하지 않습니다.
      // 그래서 항상 발견된 더 높은 버전을 사용합니다.
      shared: ['lodash'],
    }),
  ],
};
Object syntax

이 구문을 사용하면 패키지 이름을 키로 정의하고 버전(semver)을 값으로 정의할 수 있는 각 공유 라이브러리를 보다 세부적으로 제어할 수 있습니다.

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        // lodash를 공유 모듈로 추가합니다.
        // package.json 으로부터 버전을 추론합니다.
        // 4.17 이상 5 미만의 버전 중 최상위 버전을 사용하게 됩니다.
        lodash: '^4.17.0',
      },
    }),
  ],
};
Object syntax with sharing hints

이 구문을 사용하면 각 공유 패키지에 힌트를 추가로 제공할 수 있습니다. 패키지의 이름을 키로, 공유 동작을 수정하기 위한 힌트를 포함한 객체를 값으로 정의하여 제공할 수 있습니다.

const deps = require('./package.json').dependencies;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        // react를 공유 모듈로 추가합니다.
        react: {
          requiredVersion: deps.react,
          singleton: true,
        },
      },
    }),
  ],
};

Sharing hints

eager

boolean

이 힌트를 사용하면 webpack이 비동기식 요청을 통해 라이브러리를 가져오는 대신 제공된 모듈이나 대체 모듈을 직접 포함할 수 있습니다. 즉, 초기 청크에서 이 공유 모듈을 사용할 수 있습니다. 또한 이 힌트가 활성화되면 제공된 모든 모듈과 대체 모듈이 항상 다운로드된다는 점에 주의해야 합니다.

import

false | string

제공된 모듈은 공유 유효범위에 배치되어야 합니다. 이 제공된 모듈은 공유 유효범위에 공유 모듈이 없거나 버전이 유효하지 않은 경우 대체 모듈 역할도 합니다. (이 힌트의 값은 기본적으로 프로퍼티 이름으로 설정됩니다.)

packageName

string

설명 파일에서 필요한 버전을 결정하는 데 사용되는 패키지 이름입니다. ‘packageName’은 요청으로부터 패키지 이름을 자동으로 결정할 수 없는 경우에만 필요합니다.

requiredVersion

false string

이 필드는 필수 패키지 버전을 지정합니다. "^1.2.3"과 같은 시멘틱 버전 관리를 허용합니다. 또한 버전이 URL로 제공되는 경우(예: "git+ssh://git@github.com:foo/bar.git#v1.0.0") 버전을 검색합니다.

shareKey

string

요청된 공유 모듈은 공유 유효범위에서 ‘shareKey’ 키 안에서 조회됩니다.

shareScope

string

공유 범위의 이름입니다.

singleton

boolean

‘singleton’은 공유 범위에서 단일 버전의 공유 모듈만 허용합니다.(기본적으로 비활성화됨) 일부 라이브러리는 전역 내부 상태를 사용합니다.(예: react, react-dom) 따라서 한 번에 하나의 라이브러리 인스턴스만 실행하는 것이 중요합니다.

공유 범위에 동일한 종속성을 갖는 여러 버전이 있는 경우, 가장 높은 시멘틱 버전이 사용됩니다.

strictVersion

boolean

‘strictVersion’을 사용하면 버전이 유효하지 않은 경우 webpack이 공유 모듈을 거부할 수 있습니다(로컬 fallback 모듈을 사용할 수 있고 공유 모듈이 singleton이 아닌 경우 기본값은 true로 설정되고, 그렇지 않으면 false로 설정되며 필수 버전이 지정되지 않은 경우 효과가 없습니다). 필요한 버전이 없으면 런타임 오류가 발생합니다.

version

false | string

제공된 모듈의 버전입니다. Webpack이 일치하는 낮은 버전을 대체할 수 있지만, 더 높은 버전은 대체할 수 없습니다.

Webpack은 기본적으로 디펜던시의 package.json 파일에 있는 버전을 사용합니다.

Additional examples

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // vue를 공유 모듈로 추가합니다.
      // package.json 으로부터 버전을 추론합니다.
      // 항상 공유 버전을 사용하지만 공유된 vue가 2.6.5 미만 또는 3 이상 버전인 경우 경고를 출력합니다.
      shared: {
        vue: {
          requiredVersion: '^2.6.5',
          singleton: true,
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // vue를 공유 모듈로 추가합니다.
      // 제공된 로컬 버전이 없습니다.
      // 공유된 vue가 2.6.5 미만 또는 3 이상 버전이면 경고를 내보냅니다.
      shared: {
        vue: {
          import: false,
          requiredVersion: '^2.6.5',
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // vue를 공유 모듈로 추가합니다.
      // 제공된 로컬 버전이 없습니다.
      // 공유된 vue가 2.6.5 미만 또는 3 이상 버전이면 오류가 발생합니다.
      shared: {
        vue: {
          import: false,
          requiredVersion: '^2.6.5',
          strictVersion: true,
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        'my-vue': {
          // 'my-vue' 가져오기로 참조할 수 있습니다.
          import: 'vue', // 'vue' 패키지는 제공된 대체 모듈로 사용됩니다.
          shareKey: 'shared-vue', // 'shared-vue'이름으로 공유된 모듈은 공유 유효범위에 배치됩니다.
          shareScope: 'default', // 'default'로 공유 유효범위가 적용됩니다.
          singleton: true, // 공유 모듈의 단일 버전만 허용됩니다.
          strictVersion: true, // 버전이 유효하지 않을 때 공유 버전을 사용하지 말아야 합니다. fallback이 없는 Singleton 또는 모듈은 넘겨집니다. 그렇지 않으면 fallback이 사용됩니다.
          version: '1.2.3', // 공유 모듈의 버전입니다.
          requiredVersion: '^1.0.0', // 공유 모듈의 최소 버전 입니다.
        },
      },
    }),
  ],
};

NoEmitOnErrorsPlugin

NoEmitOnErrorsPlugin을 사용하면 오류가 있을 때 애셋 방출을 피할 수 있습니다. 기본적으로 활성화되어 있으며, optimization.emitOnErrors를 사용하여 비활성화 할 수 있습니다.

webpack.config.js

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

NormalModuleReplacementPlugin

NormalModuleReplacementPlugin을 사용하면 resourceRegExp와 일치하는 리소스를 newResource로 교체할 수 있습니다. newResource가 상대적인 경우 이전 리소스를 기준으로 해결됩니다. newResource가 함수인 경우 제공된 리소스의 요청 속성을 덮어쓸 것으로 예상됩니다.

이는 빌드 간에 다른 동작을 허용하는 데 유용할 수 있습니다.

new webpack.NormalModuleReplacementPlugin(resourceRegExp, newResource);

resourceRegExp는 확인된 리소스가 아니라 코드에 작성한 요청에 대해 테스트 됩니다. 예를 들어, import sum from './sum' 코드가 있을 때 './sum.js' 대신 './sum'이 테스트에 사용됩니다.

또한 Windows를 사용할 때는 다른 폴더 구분 기호를 사용해야 합니다. 예를 들어 /src\/environments\/environment\.ts/는 Windows에서 작동하지 않기 때문에, /src[\\/]environments[\\/]environment\.ts/,를 대신 사용해야 합니다.

Basic Example

개발 환경용으로 빌드할 때 특정 모듈을 교체합니다.

some/path/config.development.module.js 설정 파일과 some/path/config.production.module.js에 프로덕션용 특수 버전이 있다면

프로덕션용으로 빌드할 때 다음 플러그인을 추가합니다.

new webpack.NormalModuleReplacementPlugin(
  /some\/path\/config\.development\.js/,
  './config.production.js'
);

Advanced Example

지정된 환경에 따른 조건부 빌드에 관한 내용입니다.

다른 빌드 대상에 대한 특정 값이 포함된 설정을 원한다고 가정해 보겠습니다.

module.exports = function (env) {
  var appTarget = env.APP_TARGET || 'VERSION_A';
  return {
    plugins: [
      new webpack.NormalModuleReplacementPlugin(/-APP_TARGET$/, function (
        resource
      ) {
        resource.request = resource.request.replace(
          /-APP_TARGET/,
          `-${appTarget}`
        );

        if (resource.createData) {
          resource.createData.request = resource.request;
        }
      }),
    ],
  };
};

2개의 설정 파일을 생성합니다.

app/config-VERSION_A.js

export default {
  title: 'I am version A',
};

app/config-VERSION_B.js

export default {
  title: 'I am version B',
};

그다음 정규 표현식에서 찾고 있는 키워드를 사용하여 해당 설정을 가져옵니다.

import config from 'app/config-APP_TARGET';
console.log(config.title);

이제 빌드하려는 대상에 따라 올바른 설정을 가져올 수 있습니다.

npx webpack --env APP_TARGET=VERSION_A
=> 'I am version A'

npx webpack --env APP_TARGET=VERSION_B
=> 'I am version B'

PrefetchPlugin

일반 모듈의 요청을 프리페치하면 첫 번째에 import 또는 require가 발생하기 전에 요청을 확인하고 빌드합니다. 플러그인을 사용함으로써 성능을 높일 수 있습니다. 영리한 프리페칭 지점을 결정하기 위해, 먼저 빌드를 프로파일링 하세요.

new webpack.PrefetchPlugin([context], request);

Options

  • context: 디렉터리에 대한 절대경로
  • request: 일반 모듈에 대한 요청 문자열

ProfilingPlugin

플러그인 실행 시간이 포함된 Chrome 프로필 파일을 생성합니다. 기본적으로 events.json 파일을 출력합니다. outputPath옵션을 사용하여 커스텀 파일 경로를 제공할 수 있습니다.

참고: ProfilingPlugin은 절대 경로만 사용합니다.

Options

  • outputPath: 커스텀 출력 파일(json)의 절대 경로

Usage: default

new webpack.debug.ProfilingPlugin();

Usage: custom outputPath

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

프로필 파일을 보기 위해서는 다음과 같은 과정을 따릅니다.

  1. ProfilingPlugin과 함께 webpack을 실행합니다.
  2. Chrome으로 이동하여 DevTools를 열고 Performance 탭(이전 명칭 Timeline)으로 이동합니다.
  3. 생성된 파일(기본 값 events.json)을 profiler로 끌어다 놓습니다.

위와 같은 과정을 거치면 plugin당 timeline 통계와 호출들이 표시될 것입니다!

ProgressPlugin

ProgressPlugin은 컴파일 도중에 진행 상황을 보고받을 방법을 자신이 원하는대로 정하는 방법을 제공합니다.

Usage

ProgressPlugin의 인스턴스를 만들고, 허용되는 여러 매개변수 중 하나를 제공하며, 기본 핸들러를 사용자 지정하는 데 사용할 수 있는 정적 메서드 createDefaultHandler도 있습니다.

Providing function

훅이 진행 상황을 보고할 때 호출될 handler 함수를 제공합니다. 함수 handler의 실행 인자:

  • percentage: 컴파일의 성공 확률을 나타내는 0과 1 사이의 숫자
  • message: 현재 실행중인 훅에 대한 짧은 설명
  • ...args: 현재 실행 상황을 묘사하는 0개 이상의 추가적인 문자열
const handler = (percentage, message, ...args) => {
  // 예를 들어, 각 진행 메세지를 콘솔에 직접 출력
  console.info(percentage, message, ...args);
};

new webpack.ProgressPlugin(handler);

Providing object

ProgressPluginobject를 제공할 때, 다음의 속성이 지원됩니다

  • activeModules (boolean = false): 활성화된 모듈의 수와 활성화된 모듈 하나를 진행 메세지로 보여줍니다.
  • entries (boolean = true): 엔트리 수를 진행 메세지로 보여줍니다.
  • handler (Providing function을 보세요)
  • modules (boolean = true): 모듈 수를 진행 메세지로 보여줍니다.
  • modulesCount (number = 5000): 시작할 모듈 수의 최솟값이며 modules 속성이 활성화되면 적용됩니다.
  • profile (boolean = false): 진행 단계의 프로필 정보를 수집하도록 ProgressPlugin에게 알려줍니다.
  • dependencies (boolean = true): 종속성 수를 진행 메세지로 보여줍니다.
  • dependenciesCount (number = 10000): 시작할 종속성 수의 최솟값이며 dependencies 속성이 활성화되면 적용됩니다.
  • percentBy (string = null: 'entries' | 'dependencies' | 'modules' | null): 진행률을 계산할 방법을 ProgressPlugin에게 알려줍니다.
new webpack.ProgressPlugin({
  activeModules: false,
  entries: true,
  handler(percentage, message, ...args) {
    // 사용자 지정 로직
  },
  modules: true,
  modulesCount: 5000,
  profile: false,
  dependencies: true,
  dependenciesCount: 10000,
  percentBy: null,
});

webpack.ProgressPlugin.createDefaultHandler

ProgressPlugin의 기본 핸들러가 요구 사항을 충족하지 않는 경우 정적 ProgressPlugin.createDefaultHandler 메서드를 사용하여 사용자 지정할 수 있습니다.

static createDefaultHandler: (
  profile: undefined | null | boolean,
  logger: WebpackLogger
) => (percentage: number, msg: string, ...args: string[]) => void;

Percentage calculation

기본적으로 진행률은 빌드된 모듈 수와 총 모듈 수를 기반으로 계산됩니다: built / total

총 모듈 수는 사전에는 알 수 없고 빌드를 거치면서 변합니다. 이는 부정확한 진행률을 야기할 수 있습니다.

이러한 문제를 해결하기 위해 ProgressPlugin은 마지막으로 알려진 총 모듈 수를 캐시하여 이 값을 다음 빌드 때 재사용합니다. 첫 번째 빌드는 데이터 값을 메모리에 캐시하지만 그 다음 빌드들은 이 값을 사용하고 업데이트합니다.

다중 구성된 엔트리 포인트가 있는 프로젝트들을 위한 설정에는 percentBy: 'entries'를 사용할 것을 추천합니다. 엔트리 포인트의 개수를 미리 알 수 있기 때문에 확률 계산은 더욱 정확해질 것입니다.

Supported Hooks

다음 훅은 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

모듈을 import 또는 require 할 필요 없이 자동으로 로드합니다.

new webpack.ProvidePlugin({
  identifier: 'module1',
  // ...
});

또는

new webpack.ProvidePlugin({
  identifier: ['module1', 'property1'],
  // ...
});

기본적으로, 모듈 해석 경로는 현재 폴더 (./**)node_modules입니다.

또한 전체 경로도 지정할 수 있습니다.

const path = require('path');

new webpack.ProvidePlugin({
  identifier: path.resolve(path.join(__dirname, 'src/module1')),
  // ...
});

모듈에서 자유 변수로 식별자를 만날 때마다 모듈이 자동으로 로드되고, 식별자가 로드된 모듈의 exports(혹은 지정된 exports를 돕기 위한 프로퍼티)로 채워집니다.

ES2015 모듈의 기본 export를 가져오려면 모듈의 기본 프로퍼티를 지정해야 합니다.

Usage: jQuery

jquery를 자동으로 로드하려면 해당 노드 모듈에 노출되는 두 변수를 모두 가리킬 수 있습니다.

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

소스 코드 중 어느 것이라도 동일합니다.

// 모듈에서
$('#item'); // <= 동작합니다.
jQuery('#item'); // <= 이 또한 동작합니다.
// $는 모듈 "jquery" exports로 자동 설정되었습니다.

Usage: jQuery with Angular 1

Angular는 jQuery가 존재하는지 찾기 위해 window.jQuery를 찾습니다. 소스 코드를 참고하세요.(https://github.com/angular/angular.js/blob/v1.5.9/src/Angular.js#L1821-L1823).

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

이 플러그인을 사용하면 소스맵 생성을 더욱더 세밀하게 제어 할 수 있습니다. 이 플러그인은 devtool의 설정 옵션을 통해 자동으로 활성화됩니다.

new webpack.SourceMapDevToolPlugin(options);

Options

다음과 같은 옵션이 제공됩니다.

  • test (string RegExp [string, RegExp]): 확장자에 따라 소스맵을 포함합니다. (기본값은 .js, .mjs.css).

  • include (string RegExp [string, RegExp]): 값과 일치하는 경로의 소스맵을 포함합니다.

  • exclude (string RegExp [string, RegExp]): 값과 일치하는 모듈을 소스맵 생성에서 제외합니다.

  • filename (string): 소스맵의 파일 이름을 정의합니다 (값이 제공되지 않으면 인라인으로 설정됩니다).

  • append (string function false): 기존 애셋에 값을 추가합니다. 일반적으로 #sourceMappingURL 주석이 사용됩니다. [url]은 소스맵 파일의 URL로 대체됩니다. Webpack v4.36.0부터는 [chunk], [filename][contenthash]와 같은 경로 파라미터가 지원됩니다. false로 설정하면 값 추가가 비활성화됩니다.

    버전 5.84.0부터 webpack은 경로와 애셋 정보 객체를 인수로 받아들이고 문자열을 반환하는 'append' 옵션을 허용합니다.

    (pathData: PathData, assetInfo?: AssetInfo) => string;
  • moduleFilenameTemplate (string): output.devtoolModuleFilenameTemplate를 참고하세요.

  • fallbackModuleFilenameTemplate (string): 위 링크를 참고하세요.

  • namespace (string): output.devtoolNamespace를 참고하세요.

  • module = true (boolean): 로더가 소스맵을 생성해야 하는지 여부를 나타냅니다.

  • columns = true (boolean): 열 매핑을 사용해야 하는지 여부를 나타냅니다.

  • noSources = false (boolean): 소스의 내용이 소스맵에 포함되지 않도록 합니다.

  • publicPath (string): public path 접두사와 함께 절대 URL을 내보냅니다. (예: https://example.com/project/)

  • fileContext (string): 이 디렉터리를 기준으로 [file] 인수를 만듭니다.

  • sourceRoot (string): 소스맵의 sourceRoot 프로퍼티에 커스텀 값을 제공합니다.

fileContext 옵션은 ../../가 절대 [url]에 나타나지 않도록 상위 디렉터리에 소스맵을 저장하려는 경우에 유용합니다.

Examples

다음은 이 플러그인의 몇 가지 일반적인 사용 사례입니다.

Basic Use Case

다음 코드를 사용하여 설정 옵션 devtool: inline-source-map을 커스텀 플러그인 설정으로 동등하게 바꿀 수 있습니다.

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

Exclude Vendor Maps

다음 코드는 vendor.js 번들 내 모듈의 소스맵을 제외합니다.

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

Host Source Maps Externally

소스맵의 URL을 설정하세요. 인증이 필요한 호스트에 호스팅하는 데 유용합니다.

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

소스맵이 상위 디렉터리에 저장되는 경우,

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

원래 청크(및 그 안에 가져온 모듈)는 webpack 내부 그래프에서 부모-자식 관계로 연결되었습니다. CommonsChunkPlugin은 중복되는 의존성을 피하고자 사용되었지만, 추가 최적화는 불가능했습니다.

webpack v4부터 optimization.splitChunks를 위해 CommonsChunkPlugin은 제거되었습니다.

Defaults

즉시 사용 가능한 SplitChunksPlugin은 대부분의 사용자에게 잘 작동합니다.

초기 청크를 변경하면 HTML 파일이 프로젝트를 실행하기 위해 포함해야 하는 스크립트 태그에 영향을 미치기 때문에 기본적으로 on-demand 청크에만 영향을 미칩니다.

Webpack은 다음 조건에 따라 자동으로 청크를 분할합니다.

  • 새 청크를 공유 할 수 있거나 모듈이 node_modules 폴더에 있는 경우
  • 새 청크가 20kb보다 클 경우(min+gz 이전에)
  • 요청 시 청크를 로드할 때 최대 병렬 요청 수가 30개 이하일 경우
  • 초기 페이지 로드 시 최대 병렬 요청 수가 30개 이하일 경우

마지막 두 가지 조건을 충족하려고 할 때 더 큰 청크가 선호됩니다.

Configuration

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은 출처와 청크 이름을 사용하여 이름을 생성합니다(예: vendors~main.js). 이 옵션을 사용하면 생성된 이름에 사용할 구분 기호를 지정할 수 있습니다.

splitChunks.chunks

string = 'async' function (chunk) RegExp

이것은 최적화를 위해 선택될 청크를 나타냅니다. 문자열이 제공될 때 유효한 값은 all, asyncinitial입니다. all을 제공하는 것은 비동기 청크와 동기 청크 간에도 청크를 공유할 수 있다는 것을 의미하기 때문에 특히 강력할 수 있습니다.

대체 캐시 그룹(splitChunks.fallbackCacheGroup.chunks)에도 적용됩니다.

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      // 모든 유형의 청크를 포함합니다.
      chunks: 'all',
    },
  },
};

또는 더 많은 제어를 위한 기능을 제공할 수 있습니다. 반환 값은 각 청크를 포함할지 여부를 나타냅니다.

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks(chunk) {
        // `my-excluded-chunk`를 제외합니다.
        return chunk.name !== 'my-excluded-chunk';
      },
    },
  },
};

Webpack 버전 5.86.0 이상을 사용하는 경우 정규식을 전달할 수도 있습니다.

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: /foo/,
    },
  },
};

splitChunks.maxAsyncRequests

number = 30

on-demand 로드 시의 최대 병렬 요청 수입니다.

splitChunks.maxInitialRequests

number = 30

엔트리 포인트의 최대 병렬 요청 수입니다.

splitChunks.defaultSizeTypes

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

크기에 숫자를 사용할 때 적용되는 크기 유형을 설정합니다.

splitChunks.minChunks

number = 1

모듈이 분할 전에 청크 간에 공유되어야 하는 최소 개수입니다.

splitChunks.hidePathInfo

boolean

maxSize로 분할된 부분의 이름을 만들 때 경로 정보가 노출되지 않도록 합니다.

splitChunks.minSize

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

생성할 청크의 최소 byte 크기입니다.

splitChunks.minSizeReduction

number { [index: string]: number }

청크를 생성하는 데 필요한 기본 청크(번들)의 바이트 단위의 줄어들 최소 크기입니다. 즉, 청크로 분할해도 기본 청크(번들)의 크기가 주어진 바이트만큼 줄어들지 않으면 splitChunks.minSize 값을 충족하더라도 분할되지 않습니다.

splitChunks.enforceSizeThreshold

splitChunks.cacheGroups.{cacheGroup}.enforceSizeThreshold

number = 50000

분할이 적용되고 기타 제한(minRemainingSize, maxAsyncRequests, maxInitialRequests)이 무시되는 임계 크기 값입니다.

splitChunks.minRemainingSize

splitChunks.cacheGroups.{cacheGroup}.minRemainingSize

number = 0

splitChunks.minRemainingSize 옵션은 분할 후 남아있는 청크의 최소 크기가 제한을 초과하도록 하여 크기가 0인 모듈을 방지하기 위해 webpack 5에 도입되었습니다. '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 byte보다 큰 청크를 더 작은 부분으로 분할하도록 합니다. 분할된 크기는 최소 minSize(maxSize 다음)입니다. 알고리즘은 결정론적이며 모듈 변경은 로컬에만 영향을 미칩니다. 따라서 장기 캐싱을 사용할 때 사용할 수 있으며 기록이 필요하지 않습니다. maxSize는 힌트일 뿐이며 모듈이 maxSize 보다 크거나 분할이 minSize를 벗어날 때 위반될 수 있습니다.

청크에 이미 이름이 있는 경우 각 부분은 해당 이름에서 파생된 새 이름을 얻습니다. optimization.splitChunks.hidePathInfo의 값에 따라 첫 번째 모듈 이름이나 해시에서 파생된 키를 추가합니다.

maxSize 옵션은 HTTP/2 및 장기 캐싱과 함께 사용하기 위한 것입니다. 더 나은 캐싱을 위해 요청수가 증가합니다. 빠른 재구축을 위해 파일 크기를 줄이는 데도 사용할 수 있습니다.

splitChunks.maxAsyncSize

number

maxSize와 마찬가지로 maxAsyncSize는 전역적으로(splitChunks.maxAsyncSize) 캐시 그룹(splitChunks.cacheGroups.{cacheGroup}.maxAsyncSize) 또는 대체 캐시 그룹(splitChunks.fallbackCacheGroup.maxAsyncSize)에 적용될 수 있습니다.

maxAsyncSizemaxSize의 차이점은 maxAsyncSize가 on-demand 로딩 청크에만 영향을 미친다는 점입니다.

splitChunks.maxInitialSize

number

maxSize와 마찬가지로 maxInitialSize는 전역적으로(splitChunks.maxInitialSize) 캐시 그룹(splitChunks.cacheGroups.{cacheGroup}.maxInitialSize) 또는 대체 캐시 그룹(splitChunks.fallbackCacheGroup.maxInitialSize)에 적용될 수 있습니다.

maxInitialSizemaxSize의 차이점은 maxInitialSize가 초기 로딩 청크 에만 영향을 미친다는 것입니다.

splitChunks.name

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

또한 splitChunks.cacheGroups.{cacheGroup}.name와 같이 각 캐시 그룹에 대해서도 사용 가능합니다.

이는 분할 청크의 이름입니다. false를 제공하면 청크의 이름이 동일하게 유지되므로 불필요하게 이름이 변경되지 않습니다. 프로덕션 빌드에 권장되는 값입니다.

문자열이나 함수를 제공하면 이름을 커스텀 할 수 있습니다. 항상 같은 문자열을 반환하는 문자열이나 함수를 지정하면 모든 공통 모듈과 vendor가 단일 청크로 병합됩니다. 이로 인해 초기 다운로드가 더 커지고 페이지 로드가 느려질 수 있습니다.

함수를 명시한 경우 청크의 이름을 선택하는 데 특히 유용한 chunk.name 속성(여기서 chunkchunks 배열의 요소)을 찾을 수 있습니다.

splitChunks.name엔트리 포인트이름과 일치하면 엔트리 포인트 청크 및 캐시 그룹이 단일 청크로 결합됩니다.

main.js

import _ from 'lodash';

console.log(_.join(['Hello', 'webpack'], ' '));

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/,
          // 여기서 cacheGroupKey는 cacheGroup의 키로 `commons`입니다.
          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 할 파일의 이름을 수정(mangle)하고 사용하지 않는 export를 생략하고 보다 효율적인 코드를 생성하기 위해 어떤 export를 사용하는지 알아봅니다. true인 경우 각 런타임에 대해 사용된 export를 분석하고, "global"인 경우 결합한 모든 런타임에 대해 전역적으로 export를 분석합니다.

splitChunks.cacheGroups

캐시 그룹은 splitChunks.*의 모든 옵션을 상속 및(또는) 재정의할 수 있습니다. 그러나 test, priorityreuseExistingChunk는 캐시 그룹 수준에서만 구성할 수 있습니다. 기본 캐시 그룹을 비활성화하려면 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

현재 청크에 이미 기본 번들에서 분리된 모듈이 포함되어 있으면 새로 생성되는 대신 재사용됩니다. 이것은 청크의 파일 이름에 영향을 줄 수 있습니다.

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

캐시 그룹에 의해 선택되는 모듈을 제어합니다. 생략하면 모든 모듈이 선택됩니다. 이는 절대 경로 모듈 리소스 또는 청크 이름과 일치할 수 있습니다. 청크 이름이 일치하면 청크의 모든 모듈이 선택됩니다.

아래와 같이 {cacheGroup}.test에 기능을 제공합니다.

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        svgGroup: {
          test(module) {
            // `module.resource`는 디스크에 있는 파일의 절대 경로를 포함합니다.
            // 플랫폼 간 호환성을 위해 / 또는 \ 대신 `path.sep`을 사용합니다.
            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';
          },
        },
      },
    },
  },
};

modulechunks 객체에서 어떤 정보를 사용할 수 있는지 확인하려면 콜백에 debugger; 문을 넣으면 됩니다. 그런 다음 디버그 모드에서 webpack 빌드를 실행하여 Chromium DevTools의 파라미터를 검사합니다.

아래는 {cacheGroup}.testRegExp를 제공한 경우입니다.

webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        defaultVendors: {
          // 플랫폼 간 호환성을 위한 경로 구분 기호로 `[\\/]`의 사용에 유의하세요.
          test: /[\\/]node_modules[\\/]|vendor[\\/]analytics_provider|vendor[\\/]other_lib/,
        },
      },
    },
  },
};

splitChunks.cacheGroups.{cacheGroup}.filename

string function (pathData, assetInfo) => string

초기 청크인 경우에만 파일 이름을 재정의할 수 있습니다. 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) => {
            // 요구 사항에 따라 파일 이름 문자열을 생성하기 위해 pathData 객체를 사용하세요.
            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.minSize, splitChunks.minChunks, splitChunks.maxAsyncRequestssplitChunks.maxInitialRequests 옵션을 무시하고 항상 이 캐시 그룹에 대한 청크를 생성하도록 지시합니다.

webpack.config.js

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

splitChunks.cacheGroups.{cacheGroup}.idHint

string

청크 ID에 대한 힌트를 설정합니다. 청크의 파일 이름에 추가됩니다.

webpack.config.js

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

Examples

Defaults: Example 1

// index.js

import('./a'); // 동적 import
// a.js
import 'react';

//...

결과: react를 포함하는 별도의 청크가 생성됩니다. import 호출에서 이 청크는 ./a를 포함하는 원래 청크와 병렬로 로드됩니다.

이유:

  • 조건 1: 청크는 node_modules의 모듈을 포함합니다
  • 조건 2: react가 30kb보다 큽니다
  • 조건 3: import 호출 시 병렬 요청 수는 2입니다
  • 조건 4: 초기 페이지 로드 시 요청에 영향을 주지 않습니다

이 이유는 무엇일까요? react는 애플리케이션 코드만큼 자주 변경되지 않을 것입니다. 별도의 청크로 이동하면 이 청크를 앱 코드와 별도로 캐시할 수 있습니다(청크 해시, 레코드, Cache-Control 또는 장기 캐시 접근 방식을 사용한다고 가정합니다).

Defaults: Example 2

// entry.js

// 동적 imports
import('./a');
import('./b');
// a.js
import './helpers'; // helpers의 크기는 40kb입니다

//...
// b.js
import './helpers';
import './more-helpers'; // more-helpers 또한 40kb의 크기를 가집니다

//...

결과: ./helpers와 이에 대한 모든 의존성을 포함하는 별도의 청크가 생성됩니다. import 호출에서 이 청크는 원래 청크와 병렬로 로드됩니다.

이유:

  • 조건 1: 청크는 두 import 호출 간에 공유됩니다
  • 조건 2: helpers는 30kb보다 큽니다
  • 조건 3: import 호출 시 병렬 요청 수는 2입니다
  • 조건 4: 초기 페이지 로드 시 요청에 영향을 주지 않습니다

helpers의 내용을 각 청크에 넣으면 코드가 두 번 다운로드됩니다. 별도의 청크를 사용하면 한 번만 발생합니다. 우리는 추가 요청 비용을 지불하며 이는 절충안으로 간주할 수 있습니다. 그렇기 때문에 최소 크기는 30kb입니다.

Split Chunks: Example 1

엔트리 포인트 간에 공유되는 모든 코드를 포함하는 commons 청크를 만듭니다.

webpack.config.js

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

Split Chunks: Example 2

전체 애플리케이션에서 node_modules의 모든 코드를 포함하는 vendors 청크를 만듭니다.

webpack.config.js

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

Split Chunks: Example 3

RegExp와 일치하는 특정 node_modules 패키지를 포함하는 custom vendor 청크를 만듭니다.

webpack.config.js

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

StylelintWebpackPlugin

npm node tests coverage discussion size

This version of stylelint-webpack-plugin only works with webpack 5. For the webpack 4, see the 2.x branch.

This plugin uses stylelint that helps you avoid errors and enforce conventions in your styles.

Getting Started

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

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

or

yarn add -D stylelint-webpack-plugin

or

pnpm add -D stylelint-webpack-plugin

[!NOTE]

You also need to install stylelint >= 13 from npm, if you haven't already:

npm install stylelint --save-dev

or

yarn add -D stylelint

or

pnpm add -D stylelint

[!NOTE]

If you are using Stylelint 13 rather than 14+, you might also need to install @types/stylelint as a dev dependency if getting stylelint related type errors.

Then add the plugin to your webpack config. For example:

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

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

Options

See stylelint's options for the complete list of options available. These options are passed through to the stylelint directly.

cache

  • Type:
type cache = boolean;
  • Default: true

The cache is enabled by default to decrease execution time.

cacheLocation

  • Type:
type cacheLocation = string;
  • Default: node_modules/.cache/stylelint-webpack-plugin/.stylelintcache

Specify the path to the cache location. Can be a file or a directory.

configFile

  • Type:
type context = string;
  • Default: undefined

Specify the config file location to be used by stylelint.

Note:

By default this is handled by stylelint.

context

  • Type:
type context = string;
  • Default: compiler.context

A string indicating the root of your files.

exclude

  • Type:
type exclude = string | Array<string>;
  • Default: ['node_modules', compiler.options.output.path]

Specify the files and/or directories to exclude. Must be relative to options.context.

extensions

  • Type:
type extensions = string | Array<string>;
  • Default: ['css', 'scss', 'sass']

Specify extensions that should be checked.

files

  • Type:
type files = string | Array<string>;
  • Default: null

Specify directories, files, or globs. Must be relative to options.context. Directories are traversed recursively looking for files matching options.extensions. File and glob patterns ignore options.extensions.

fix

  • Type:
type fix = boolean;
  • Default: false

If true, stylelint will fix as many errors as possible. The fixes are made to the actual source files. All unfixed errors will be reported. See Autofixing errors docs.

formatter

  • Type:
type formatter = string | (
  results: Array<import('stylelint').LintResult>
) => string
  • Default: 'string'

Specify the formatter that you would like to use to format your results. See formatter option.

lintDirtyModulesOnly

  • Type:
type lintDirtyModulesOnly = boolean;
  • Default: false

Lint only changed files, skip lint on start.

stylelintPath

  • Type:
type stylelintPath = string;
  • Default: stylelint

Path to stylelint instance that will be used for linting.

threads

  • Type:
type threads = boolean | number;
  • Default: false

Set to true for an auto-selected pool size based on number of cpus. Set to a number greater than 1 to set an explicit pool size. Set to false, 1, or less to disable and only run in main process.

Errors and Warning

By default the plugin will auto adjust error reporting depending on stylelint errors/warnings counts. You can still force this behavior by using emitError or emitWarning options:

emitError

  • Type:
type emitError = boolean;
  • Default: true

The errors found will always be emitted, to disable set to false.

emitWarning

  • Type:
type emitWarning = boolean;
  • Default: true

The warnings found will always be emitted, to disable set to false.

failOnError

  • Type:
type failOnError = boolean;
  • Default: true

Will cause the module build to fail if there are any errors, to disable set to false.

failOnWarning

  • Type:
type failOnWarning = boolean;
  • Default: false

Will cause the module build to fail if there are any warnings, if set to true.

quiet

  • Type:
type quiet = boolean;
  • Default: false

Will process and report errors only and ignore warnings, if set to true.

outputReport

  • Type:
type outputReport =
  | boolean
  | {
      filePath?: string | undefined;
      formatter?:
        | (
            | string
            | ((results: Array<import('stylelint').LintResult>) => string)
          )
        | undefined;
    };
  • Default: false

Write the output of the errors to a file, for example a json file for use for reporting. The filePath is relative to the webpack config: output.path. You can pass in a different formatter for the output file, if none is passed in the default/configured formatter will be used.

{
  filePath: 'path/to/file';
  formatter: 'json';
}

Changelog

Changelog

License

MIT

SvgChunkWebpackPlugin

GitHub Workflow Status (branch) Coverage Status Npm downloads

The svg-chunk-webpack-plugin creates optimized SVG sprites, according to Webpack's entrypoints. Each sprite contains only the SVG dependencies listed on its entrypoints to improved code splitting, even on SVG files.

The plugin includes the popular SVGO package to generates clean and optimized SVG sprites.

Code splitting is the key to deliver files without any content that is unused by the pages. It already exists for CSS, Javascript and now for SVG files with this plugin.

When to use this plugin

On multiple page application, each pages must includes only its necessary dependencies. In other words, it must include only the SVG files imported by its entrypoint and all its dependencies.

With reusable components, SVGs are often duplicated on all the project. Now, you can create a global SVG library and every Javascript files can easily import any SVG from this library. Entrypoint dependencies are automatically updated, thanks to the Webpack compilation.

When you work with SVGs exported by design softwares, like Sketch or Illustrator, their source code is never optimized and often contains comments, CSS classes which can create conflicts between them. The plugin automatically cleans all SVGs before creating the sprite.

Zero config

The plugin works without configuration with already the optimized settings. For advanced usage, see the section using configuration.

Installation

The plugin is available as a package with the name of svg-chunk-webpack-plugin on npm and Github.

npm install svg-chunk-webpack-plugin --save-dev
yarn add svg-chunk-webpack-plugin --dev

Warning svg-chunk-webpack-plugin@5 is ESM only.

Note Minimum supported Node.js version is 16.20.0 and Webpack >=5.10.3.

Example

The project includes a minimalist example in the ./example directory. Run the npm run build:example command to execute the Webpack example and see the plugin's implementation in action.

Basic usage

The plugin will generate one SVG sprite for each entrypoints. Sprites are built in the output path directory with all the other assets. Each sprite filename is composed with its entrypoint name (in the example below, that would be home.svg).

First, let's add the loader and the plugin to the Webpack configuration.

Warning The loader and the plugin need to works together.

webpack.config.js

import SvgChunkWebpackPlugin from 'svg-chunk-webpack-plugin';

export default {
  module: {
    rules: [
      {
        test: /\.svg$/,
        use: [
          {
            loader: SvgChunkWebpackPlugin.loader
          }
        ]
      }
    ]
  },
  plugins: [new SvgChunkWebpackPlugin()]
};

Note

For more flexibility and better performance, inline SVG files are better. Fewer HTTP requests, CSS properties to change the style, no flickering during the page load.

Then, include the sprite in the wanted pages (we use Twig in the following example).

home.html.twig

{{ include 'home.svg' }}

Finally, use the SVG with the <use> tag, like the following example. Replace <svg_name> by the SVG name (without the extension).

home.html.twig

<svg>
  <use href="#<svg_name>"></use>
</svg>

Using a configuration

The loader and the plugin accepts configuration to override the default behavior.

Loader

The loader configuration allow to personalize the SVGO configuration. SVGO optimization is executed during the loader process to optimize build performance.

configFile

Type:

type configFile = string | boolean;

Default: path.resolve(opts.root, 'svgo.config.js')

Tells the loader whether to load the custom SVGO configuration. Custom configuration can be disabled with configFile: false.

webpack.config.js

export default {
  module: {
    rules: [
      {
        test: /\.svg$/,
        loader: SvgChunkWebpackPlugin.loader,
        options: {
          configFile: './path/svgo.config.js'
        }
      }
    ]
  }
};

SVGO custom configuration

SVGO have a default preset to optimize SVG files. See how to configure svgo for details.

svgo.config.js

export default {
  multipass: true,
  plugins: [
    {
      name: 'preset-default',
      params: {
        overrides: {
          inlineStyles: {
            onlyMatchedOnce: false
          },
          removeViewBox: false
        }
      }
    },
    {
      name: 'convertStyleToAttrs'
    }
  ]
};

Plugin

The plugin configuration allow to personalize sprite settings.

filename

Type:

type filename = string;

Default: '[name].svg'

Tells the plugin whether to personalize the default sprite filename. The placeholder [name] is automatically replaced by entrypoints names.

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      filename: '[name].svg'
    })
  ]
};

Note The filename parameter is compatible with Webpack caching placeholders, see the section caching.

svgstoreConfig

Type:

type svgstoreConfig = object;

Default: { cleanDefs: false, cleanSymbols: false, inline: true }

SVG sprites are built using the svgstore package. Update the parameters according to your needs from the options list available on the svgstore documentation.

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      svgstoreConfig: {
        svgAttrs: {
          'aria-hidden': true,
          style: 'position: absolute; width: 0; height: 0; overflow: hidden;'
        }
      }
    })
  ]
};

Note To avoid LinearGradient conflicts, avoid the display: none property which breaks SVG definitions.

generateSpritesManifest

Type:

type generateSpritesManifest = boolean;

Default: false

Tells the plugin whether to generate the sprites-manifest.json. The JSON file contains the list of all SVG included by entrypoints.

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      generateSpritesManifest: true
    })
  ]
};

generateSpritesPreview

Type:

type generateSpritesPreview = boolean;

Default: false

Tells the plugin whether to generate the sprites-preview.html. The HTML preview contains a display list of all SVG included by entrypoints with the SVG overviews and the names. See the sprites preview of the example.

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      generateSpritesPreview: true
    })
  ]
};

Caching

With webpack caching, several placeholders are available depending on your needs. With SVG inlined in the page, this option is not useful.

Note

The [contenthash] placeholder is the best option because it depends on the sprite content. Cache placeholders are expensive in build performance, use it only in production mode.

[contenthash]

The [contenthash] placeholder will add a unique hash based on the content of the sprite. When the sprite's content changes, the hash will change as well.

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      filename: '[name].[contenthash].svg'
    })
  ]
};

[fullhash]

The [fullhash] placeholder will add a unique hash generated for every build. When the compilation build is updated, the hash will change as well.

webpack.config.js

export default {
  plugins: [
    new SvgChunkWebpackPlugin({
      filename: '[name].[fullhash].svg'
    })
  ]
};

License

svg-chunk-webpack-plugin is licensed under the MIT License.

Created with ♥ by @yoriiis.

TerserWebpackPlugin

npm node tests cover discussion size

This plugin uses terser to minify/minimize your JavaScript.

Getting Started

Webpack v5 comes with the latest terser-webpack-plugin out of the box. If you are using Webpack v5 or above and wish to customize the options, you will still need to install terser-webpack-plugin. Using Webpack v4, you have to install terser-webpack-plugin v4.

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

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

or

yarn add -D terser-webpack-plugin

or

pnpm add -D terser-webpack-plugin

Then add the plugin to your webpack config. For example:

webpack.config.js

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

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

And run webpack via your preferred method.

Note about source maps

Works only with source-map, inline-source-map, hidden-source-map and nosources-source-map values for the devtool option.

Why?

  • eval wraps modules in eval("string") and the minimizer does not handle strings.
  • cheap has not column information and minimizer generate only a single line, which leave only a single mapping.

Using supported devtool values enable source map generation.

Options

test

Type:

type test = string | RegExp | Array<string | RegExp>;

Default: /\.m?js(\?.*)?$/i

Test to match files against.

webpack.config.js

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

include

Type:

type include = string | RegExp | Array<string | RegExp>;

Default: undefined

Files to include.

webpack.config.js

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

exclude

Type:

type exclude = string | RegExp | Array<string | RegExp>;

Default: undefined

Files to exclude.

webpack.config.js

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

parallel

Type:

type parallel = boolean | number;

Default: true

Use multi-process parallel running to improve the build speed. Default number of concurrent runs: os.cpus().length - 1.

Note

Parallelization can speedup your build significantly and is therefore highly recommended.

Warning

If you use Circle CI or any other environment that doesn't provide real available count of CPUs then you need to setup explicitly number of CPUs to avoid Error: Call retries were exceeded (see #143, #202).

boolean

Enable/disable multi-process parallel running.

webpack.config.js

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

number

Enable multi-process parallel running and set number of concurrent runs.

webpack.config.js

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

minify

Type:

type minify = (
  input: {
    [file: string]: string;
  },
  sourceMap: import("@jridgewell/trace-mapping").SourceMapInput | undefined,
  minifyOptions: {
    module?: boolean | undefined;
    ecma?: import("terser").ECMA | undefined;
  },
  extractComments:
    | boolean
    | "all"
    | "some"
    | RegExp
    | ((
        astNode: any,
        comment: {
          value: string;
          type: "comment1" | "comment2" | "comment3" | "comment4";
          pos: number;
          line: number;
          col: number;
        }
      ) => boolean)
    | {
        condition?:
          | boolean
          | "all"
          | "some"
          | RegExp
          | ((
              astNode: any,
              comment: {
                value: string;
                type: "comment1" | "comment2" | "comment3" | "comment4";
                pos: number;
                line: number;
                col: number;
              }
            ) => boolean)
          | undefined;
        filename?: string | ((fileData: any) => string) | undefined;
        banner?:
          | string
          | boolean
          | ((commentsFile: string) => string)
          | undefined;
      }
    | undefined
) => Promise<{
  code: string;
  map?: import("@jridgewell/trace-mapping").SourceMapInput | undefined;
  errors?: (string | Error)[] | undefined;
  warnings?: (string | Error)[] | undefined;
  extractedComments?: string[] | undefined;
}>;

Default: TerserPlugin.terserMinify

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

Warning

Always use require inside minify function when parallel option enabled.

webpack.config.js

// Can be async
const minify = (input, sourceMap, minimizerOptions, extractsComments) => {
  // The `minimizerOptions` option contains option from the `terserOptions` option
  // You can use `minimizerOptions.myCustomOption`

  // Custom logic for extract comments
  const { map, code } = require("uglify-module") // Or require('./path/to/uglify-module')
    .minify(input, {
      /* Your options for minification */
    });

  return { map, code, warnings: [], errors: [], extractedComments: [] };
};

// Used to regenerate `fullhash`/`chunkhash` between different implementation
// Example: you fix a bug in custom minimizer/custom function, but unfortunately webpack doesn't know about it, so you will get the same fullhash/chunkhash
// to avoid this you can provide version of your custom minimizer
// You don't need if you use only `contenthash`
minify.getMinimizerVersion = () => {
  let packageJson;

  try {
    // eslint-disable-next-line global-require, import/no-extraneous-dependencies
    packageJson = require("uglify-module/package.json");
  } catch (error) {
    // Ignore
  }

  return packageJson && packageJson.version;
};

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

terserOptions

Type:

type terserOptions = {
  compress?: boolean | CompressOptions;
  ecma?: ECMA;
  enclose?: boolean | string;
  ie8?: boolean;
  keep_classnames?: boolean | RegExp;
  keep_fnames?: boolean | RegExp;
  mangle?: boolean | MangleOptions;
  module?: boolean;
  nameCache?: object;
  format?: FormatOptions;
  /** @deprecated */
  output?: FormatOptions;
  parse?: ParseOptions;
  safari10?: boolean;
  sourceMap?: boolean | SourceMapOptions;
  toplevel?: boolean;
};

Default: default

Terser options.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          ecma: undefined,
          parse: {},
          compress: {},
          mangle: true, // Note `mangle.properties` is `false` by default.
          module: false,
          // Deprecated
          output: null,
          format: null,
          toplevel: false,
          nameCache: null,
          ie8: false,
          keep_classnames: undefined,
          keep_fnames: false,
          safari10: false,
        },
      }),
    ],
  },
};

extractComments

Type:

type extractComments =
  | boolean
  | string
  | RegExp
  | ((
      astNode: any,
      comment: {
        value: string;
        type: "comment1" | "comment2" | "comment3" | "comment4";
        pos: number;
        line: number;
        col: number;
      }
    ) => boolean)
  | {
      condition?:
        | boolean
        | "all"
        | "some"
        | RegExp
        | ((
            astNode: any,
            comment: {
              value: string;
              type: "comment1" | "comment2" | "comment3" | "comment4";
              pos: number;
              line: number;
              col: number;
            }
          ) => boolean)
        | undefined;
      filename?: string | ((fileData: any) => string) | undefined;
      banner?:
        | string
        | boolean
        | ((commentsFile: string) => string)
        | undefined;
    };

Default: true

Whether comments shall be extracted to a separate file, (see details). By default extract only comments using /^\**!|@preserve|@license|@cc_on/i regexp condition and remove remaining comments. If the original file is named foo.js, then the comments will be stored to foo.js.LICENSE.txt. The terserOptions.format.comments option specifies whether the comment will be preserved, i.e. it is possible to preserve some comments (e.g. annotations) while extracting others or even preserving comments that have been extracted.

boolean

Enable/disable extracting comments.

webpack.config.js

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

string

Extract all or some (use /^\**!|@preserve|@license|@cc_on/i RegExp) comments.

webpack.config.js

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

RegExp

All comments that match the given expression will be extracted to the separate file.

webpack.config.js

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

function

All comments that match the given expression will be extracted to the separate file.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: (astNode, comment) => {
          if (/@extract/i.test(comment.value)) {
            return true;
          }

          return false;
        },
      }),
    ],
  },
};

object

Allow to customize condition for extract comments, specify extracted file name and banner.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: /^\**!|@preserve|@license|@cc_on/i,
          filename: (fileData) => {
            // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
            return `${fileData.filename}.LICENSE.txt${fileData.query}`;
          },
          banner: (licenseFile) => {
            return `License information can be found in ${licenseFile}`;
          },
        },
      }),
    ],
  },
};
condition

Type:

type condition =
  | boolean
  | "all"
  | "some"
  | RegExp
  | ((
      astNode: any,
      comment: {
        value: string;
        type: "comment1" | "comment2" | "comment3" | "comment4";
        pos: number;
        line: number;
        col: number;
      }
    ) => boolean)
  | undefined;

Condition what comments you need extract.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: "some",
          filename: (fileData) => {
            // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
            return `${fileData.filename}.LICENSE.txt${fileData.query}`;
          },
          banner: (licenseFile) => {
            return `License information can be found in ${licenseFile}`;
          },
        },
      }),
    ],
  },
};
filename

Type:

type filename = string | ((fileData: any) => string) | undefined;

Default: [file].LICENSE.txt[query]

Available placeholders: [file], [query] and [filebase] ([base] for webpack 5).

The file where the extracted comments will be stored. Default is to append the suffix .LICENSE.txt to the original filename.

Warning

We highly recommend using the txt extension. Using js/cjs/mjs extensions may conflict with existing assets which leads to broken code.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: /^\**!|@preserve|@license|@cc_on/i,
          filename: "extracted-comments.js",
          banner: (licenseFile) => {
            return `License information can be found in ${licenseFile}`;
          },
        },
      }),
    ],
  },
};
banner

Type:

type banner = string | boolean | ((commentsFile: string) => string) | undefined;

Default: /*! For license information please see ${commentsFile} */

The banner text that points to the extracted file and will be added on top of the original file. Can be false (no banner), a String, or a Function<(string) -> String> that will be called with the filename where extracted comments have been stored. Will be wrapped into comment.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: {
          condition: true,
          filename: (fileData) => {
            // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
            return `${fileData.filename}.LICENSE.txt${fileData.query}`;
          },
          banner: (commentsFile) => {
            return `My custom banner about license information ${commentsFile}`;
          },
        },
      }),
    ],
  },
};

Examples

Preserve Comments

Extract all legal comments (i.e. /^\**!|@preserve|@license|@cc_on/i) and preserve /@license/i comments.

webpack.config.js

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

Remove Comments

If you avoid building with comments, use this config:

webpack.config.js

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

uglify-js

UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: TerserPlugin.uglifyJsMinify,
        // `terserOptions` options will be passed to `uglify-js`
        // Link to options - https://github.com/mishoo/UglifyJS#minify-options
        terserOptions: {},
      }),
    ],
  },
};

swc

swc is a super-fast compiler written in rust; producing widely-supported javascript from modern standards and typescript.

Warning

the extractComments option is not supported and all comments will be removed by default, it will be fixed in future

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: TerserPlugin.swcMinify,
        // `terserOptions` options will be passed to `swc` (`@swc/core`)
        // Link to options - https://swc.rs/docs/config-js-minify
        terserOptions: {},
      }),
    ],
  },
};

esbuild

esbuild is an extremely fast JavaScript bundler and minifier.

Warning

the extractComments option is not supported and all legal comments (i.e. copyright, licenses and etc) will be preserved

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: TerserPlugin.esbuildMinify,
        // `terserOptions` options will be passed to `esbuild`
        // Link to options - https://esbuild.github.io/api/#minify
        // Note: the `minify` options is true by default (and override other `minify*` options), so if you want to disable the `minifyIdentifiers` option (or other `minify*` options) please use:
        // terserOptions: {
        //   minify: false,
        //   minifyWhitespace: true,
        //   minifyIdentifiers: false,
        //   minifySyntax: true,
        // },
        terserOptions: {},
      }),
    ],
  },
};

Custom Minify Function

Override default minify function - use uglify-js for minification.

webpack.config.js

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        minify: (file, sourceMap) => {
          // https://github.com/mishoo/UglifyJS2#minify-options
          const uglifyJsOptions = {
            /* your `uglify-js` package options */
          };

          if (sourceMap) {
            uglifyJsOptions.sourceMap = {
              content: sourceMap,
            };
          }

          return require("uglify-js").minify(file, uglifyJsOptions);
        },
      }),
    ],
  },
};

Typescript

With default terser minify function:

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

With built-in minify functions:

import type { JsMinifyOptions as SwcOptions } from "@swc/core";
import type { MinifyOptions as UglifyJSOptions } from "uglify-js";
import type { TransformOptions as EsbuildOptions } from "esbuild";
import type { MinifyOptions as TerserOptions } from "terser";

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin<SwcOptions>({
        minify: TerserPlugin.swcMinify,
        terserOptions: {
          // `swc` options
        },
      }),
      new TerserPlugin<UglifyJSOptions>({
        minify: TerserPlugin.uglifyJsMinify,
        terserOptions: {
          // `uglif-js` options
        },
      }),
      new TerserPlugin<EsbuildOptions>({
        minify: TerserPlugin.esbuildMinify,
        terserOptions: {
          // `esbuild` options
        },
      }),

      // Alternative usage:
      new TerserPlugin<TerserOptions>({
        minify: TerserPlugin.terserMinify,
        terserOptions: {
          // `terser` options
        },
      }),
    ],
  },
};

Contributing

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

CONTRIBUTING

License

MIT

WatchIgnorePlugin

watch 모드인 경우, 제공된 경로나 정규 표현식에 해당되는 특정 파일을 무시합니다.

new webpack.WatchIgnorePlugin({ paths });

Options

  • paths (Array<string | RegExp>): 무시해야 하는 디렉터리나 파일에 대한 정규 표현식 또는 절대 경로의 목록입니다.

1 Contributor

webpack