AutomaticPrefetchPlugin
은 변경사항을 관찰하는 동안 이전 컴파일의 모든 모듈을 미리 검색하여 증가하는 빌드 시간을 개선합니다. 단일 모듈을 미리 검색하는 PrefetchPlugin
과 비교해보세요.
webpack.config.js
module.exports = {
// ...
plugins: [new webpack.AutomaticPrefetchPlugin()],
};
생성된 각 청크의 상단에 배너를 추가합니다.
const webpack = require('webpack');
new webpack.BannerPlugin(banner);
// 또는
new webpack.BannerPlugin(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, // 배너를 주입해야 하는 컴파일 단계
}
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,
});
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]',
});
The chunks-webpack-plugin
creates HTML files with entry points and chunks relations to serve your webpack bundles. It is suitable with multi-page applications that contain multiple entry points.
Since webpack 4, SplitChunksPlugin
offers the possibility to optimizes all chunks. It can be particularly powerful, because it means that chunks can be shared even between async and non-async chunks. See the webpack documentation of splitChunks.chunks
for details.
splitChunks.chunks
option can be set to automatically generate new chunks associated with an entry point. For example, entry points a.js
and b.js
share common code with the file vendors~a~b.js
.
With multiple entry points, it can be difficult to identify relation between the auto-generated chunks and entry points.
chunks-webpack-plugin
parses the webpack compilation entry points to get all files associated with the entry points. Then, it generates HTML files which include all assets filtered by an entry point and thechunks-manifest.json
file.
It works without configuration. For advanced usage, see the using configuration section.
chunks-webpack-plugin
is available on npm as chunks-webpack-plugin
and as chunks-webpack-plugin
on GitHub.
npm install chunks-webpack-plugin --save-dev
yarn add chunks-webpack-plugin --dev
Warning
chunks-webpack-plugin@10
is ESM only.Note Minimum supported
Node.js
version is16.20.0
and Webpack>=5.10.3
.
The project includes a minimalist example in the ./example
directory. Run the npm run build:example
command to execute the Webpack example and see the plugin's implementation in action.
chunks-webpack-plugin
will generate two HTML files for each entry point. Each filename contains the entry point name, the {{entry}}
placeholder is automatically replaced.
{{entry}}-styles.html
: contains all HTML <link>
tags{{entry}}-scripts.html
: contains all HTML <script>
tagsFirst, let's add the plugin to the webpack configuration.
webpack.config.js
import ChunksWebpackPlugin from 'chunks-webpack-plugin';
export default {
plugins: [new ChunksWebpackPlugin()]
};
HTML files are built in the output path directory with the rest of the webpack compilation.
Now you can include the generated HTML files into your HTML page templates. You can do it with e.g. Twig.
main-styles.html
<link rel="stylesheet" href="main.css" />
main-scripts.html
<script defer src="main.js"></script>
You can pass a configuration object to chunks-webpack-plugin
to override the default settings.
filename
Type:
type filename = string;
Default: '[name]-[type].html'
Tells the plugin whether to personalize the filename of the generated files. Files are processed by the webpack compilation and generated in the output path directory. The placeholder [name]
is automatically replaced by entry points names and [type]
by styles|scripts
.
new ChunksWebpackPlugin({
filename: 'templates/[name]-[type].html'
});
Note The
filename
can contain directories, which will be created automatically.
templateStyle
Type:
type templateStyle = (name: string, entryName: string) => string;
Default:
(name) => `<link rel="stylesheet" href="${name}" />`;
Tells the plugin whether to personalize the default template for the HTML <style>
tags. For example, add additional attributes or a CDN prefix.
export default {
plugins: [
new ChunksWebpackPlugin({
templateStyle: (name) => `<link rel="stylesheet" href="https://cdn.domain.com${name}" />`
})
]
};
templateScript
Type:
type templateScript = (name: string, entryName: string) => string;
Default:
(name) => `<script defer src="${name}"></script>`;
Tells the plugin whether to personalize the default template for the HTML <script>
tags. For example, add additional attributes or a CDN prefix.
export default {
plugins: [
new ChunksWebpackPlugin({
templateScript: (name) => `<script defer src="https://cdn.domain.com${name}"></script>`
})
]
};
generateChunksManifest
Type:
type generateChunksManifest = boolean;
Default: false
Tells the plugin whether to generate the chunks-manifest.json
. The file contains the list of all chunks grouped by entry points. See the chunks-manifest.json example.
export default {
plugins: [
new ChunksWebpackPlugin({
generateChunksManifest: true
})
]
};
generateChunksFiles
Type:
type generateChunksFiles = boolean;
Default: true
Tells the plugin whether to generate the HTML files.
export default {
plugins: [
new ChunksWebpackPlugin({
generateChunksFiles: false
})
]
};
Warning When set to
false
, HTML files will not be generated. It can only be useful together withgenerateChunksManifest
option set totrue
for custom generation of the HTML files.
Example of the webpack configuration with multiple entry points which share common code with the splitChunks
option.
import ChunksWebpackPlugin from 'chunks-webpack-plugin';
import path from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
entry: {
home: 'home.js',
news: 'news.js'
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist')
},
plugins: [new ChunksWebpackPlugin()],
optimization: {
splitChunks: {
chunks: 'all'
}
}
};
The plugin will generate all files in the output path directory:
home-styles.html
<link rel="stylesheet" href="vendors~home~news.css" />
<link rel="stylesheet" href="home.css" />
home-scripts.html
<script defer src="vendors~home~news.js"></script>
<script defer src="home.js"></script>
news-styles.html
<link rel="stylesheet" href="vendors~home~news.css" />
<link rel="stylesheet" href="news.css" />
news-scripts.html
<script defer src="vendors~home~news.js"></script>
<script defer src="news.js"></script>
chunks-webpack-plugin
is licensed under the MIT License.
Created with ♥ by @yoriiis.
CommonsChunkPlugin
은 여러 엔트리 포인트 간에 공유되는 공통 모듈로 이루어진 별도의 파일(청크라고 합니다)을 만드는 opt-in 기능입니다.
번들에서 공통 모듈을 분리한 결과로 생성된 청크 파일을 처음에 한 번 로드하고 나중에 사용하기 위해 캐시에 저장할 수 있습니다. 이로 인해 브라우저가 새 페이지를 방문할 때마다 더 큰 번들을 로드하지 않고 캐시에서 공유 코드를 빠르게 제공할 수 있으므로 페이지 속도가 최적화됩니다.
new webpack.optimize.CommonsChunkPlugin(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,
// 공통 청크가 생성되기 전 모든 공통 모듈의 최소 사이즈입니다.
}
엔트리 포인트 간에 공유되는 공통 모듈을 포함하는 추가 청크를 생성합니다.
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>
코드를 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>
Code Splitting을 사용하면 엔트리 청크의 여러 하위(자식) 청크가 공통 종속성을 가질 수 있습니다. 중복을 방지하기 위해 이들을 부모 청크로 옮길 수 있습니다. 이렇게 하면 전체 크기가 줄어들지만, 초기 로드 시간에 부정적인 영향을 미칩니다. 사용자가 많은 형제 청크(예: 엔트리 청크의 자식)를 다운로드해야 할 것으로 예상되는 경우 전체 로드 시간이 향상됩니다.
new webpack.optimize.CommonsChunkPlugin({
// names: ["app", "subPageA"]
// (청크를 선택하거나 모든 청크를 생략하세요)
children: true,
// (선택된 청크의 모든 자식을 선택합니다)
// minChunks: 3,
// (모듈을 옮기기 전에 3명의 자식이 공유해야 합니다)
});
위의 것과 유사하지만 공통 모듈을 부모로 이동하는 대신(초기 로드 시간을 증가시키게 됩니다) 비동기식으로 로드된 새로운 추가 공통 청크가 사용됩니다. 이는 추가 청크가 다운로드되면 자동으로 병렬로 다운로드됩니다.
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
// 또는
names: ['app', 'subPageA'],
// 단일 이름 또는 배열 형태의 이름은 비동기 청크를 생성하는
// 엔트리 포인트의 이름과 일치해야 합니다.
children: true,
// (청크의 모든 자식을 사용합니다)
async: true,
// (비동기 공통 청크를 생성합니다)
minChunks: 3,
// (모듈이 분리되기 전에 3명의 자식이 모듈을 공유해야 합니다)
});
minChunks
property a function또한 minChunks
속성에 함수를 전달할 수도 있습니다. 이 함수는 CommonsChunkPlugin
에 의해 호출되며 module
및 count
인수로 함수를 호출합니다.
module
인수는 name
/names
속성을 통해 제공된 청크의 각 모듈을 나타냅니다.
module
은 NormalModule의 형태로, 이 사용 사례에 특히 유용한 두 개의 속성이 있습니다.
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');
},
});
webpack 부트스트랩 로직을 별도의 파일로 추출하려면 entry
로 정의되어 있지 않은 name
에 CommonsChunkPlugin
을 사용하세요. 자세한 내용은 캐싱 가이드를 참조하세요.
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity,
});
vendor
와 manifest
청크는 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,
}),
];
Prepare compressed versions of assets to serve them with Content-Encoding.
To begin, you'll need to install compression-webpack-plugin
:
npm install compression-webpack-plugin --save-dev
or
yarn add -D compression-webpack-plugin
or
pnpm add -D compression-webpack-plugin
Then add the plugin to your webpack
config. For example:
webpack.config.js
const CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
plugins: [new CompressionPlugin()],
};
And run webpack
via your preferred method.
test
Type:
type test = string | RegExp | Array<string | RegExp>;
Default: undefined
Include all assets that pass test assertion.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
test: /\.js(\?.*)?$/i,
}),
],
};
include
Type:
type include = string | RegExp | Array<string | RegExp>;
Default: undefined
Include all assets matching any of these conditions.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
include: /\/includes/,
}),
],
};
exclude
Type:
type exclude = string | RegExp | Array<string | RegExp>;
Default: undefined
Exclude all assets matching any of these conditions.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
exclude: /\/excludes/,
}),
],
};
algorithm
Type:
type algorithm =
| string
| ((
input: Buffer,
options: CompressionOptions,
callback: (
error: Error | null | undefined,
result:
| string
| ArrayBuffer
| SharedArrayBuffer
| Uint8Array
| readonly number[]
| {
valueOf(): ArrayBuffer | SharedArrayBuffer;
}
| {
valueOf(): string | Uint8Array | readonly number[];
}
| {
valueOf(): string;
}
| {
[Symbol.toPrimitive](hint:%20%22string%22): string;
},
) => void,
) => any);
Default: gzip
The compression algorithm/function.
[!NOTE]
If you use custom function for the
algorithm
option, the default value of thecompressionOptions
option is{}
.
string
The algorithm is taken from zlib.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
algorithm: "gzip",
}),
],
};
function
Allow to specify a custom compression function.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
algorithm(input, compressionOptions, callback) {
return compressionFunction(input, compressionOptions, callback);
},
}),
],
};
compressionOptions
Type:
type compressionOptions = {
flush?: number;
finishFlush?: number;
chunkSize?: number;
windowBits?: number;
level?: number;
memLevel?: number;
strategy?: number;
dictionary?: Buffer | TypedArray | DataView | ArrayBuffer;
info?: boolean;
maxOutputLength?: number;
};
Default: { level: 9 }
Compression options for algorithm
.
You can find all options here zlib.
[!NOTE]
If you use custom function for the
algorithm
option, the default value is{}
.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
compressionOptions: { level: 1 },
}),
],
};
threshold
Type:
type threshold = number;
Default: 0
Only assets bigger than this size are processed. In bytes.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
threshold: 8192,
}),
],
};
minRatio
Type:
type minRatio = number;
Default: 0.8
Only assets that compress better than this ratio are processed (minRatio = Compressed Size / Original Size
).
Example: you have image.png
file with 1024b size, compressed version of file has 768b size, so minRatio
equal 0.75
.
In other words assets will be processed when the Compressed Size / Original Size
value less minRatio
value.
You can use 1
value to process assets that are smaller than the original.
Use a value of Infinity
to process all assets even if they are larger than the original size or their original size is 0
bytes (useful when you are pre-zipping all assets for AWS).
Use a value of Number.MAX_SAFE_INTEGER
to process all assets even if they are larger than the original size, excluding assets with their original size is 0
bytes.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
// Compress all assets, including files with `0` bytes size
// minRatio: Infinity
// Compress all assets, excluding files with `0` bytes size
// minRatio: Number.MAX_SAFE_INTEGER
minRatio: 0.8,
}),
],
};
filename
Type:
type filename = string | ((pathdata: PathData) => string);
Default: "[path][base].gz"
The target asset filename.
string
For example we have assets/images/image.png?foo=bar#hash
:
[path]
is replaced with the directories to the original asset, included trailing /
(assets/images/
).
[file]
is replaced with the path of original asset (assets/images/image.png
).
[base]
is replaced with the base ([name]
+ [ext]
) of the original asset (image.png
).
[name]
is replaced with the name of the original asset (image
).
[ext]
is replaced with the extension of the original asset, included .
(.png
).
[query]
is replaced with the query of the original asset, included ?
(?foo=bar
).
[fragment]
is replaced with the fragment (in the concept of URL it is called hash
) of the original asset (#hash
).
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
filename: "[path][base].gz",
}),
],
};
function
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
filename(pathData) {
// The `pathData` argument contains all placeholders - `path`/`name`/`ext`/etc
// Available properties described above, for the `String` notation
if (/\.svg$/.test(pathData.filename)) {
return "assets/svg/[path][base].gz";
}
return "assets/js/[path][base].gz";
},
}),
],
};
deleteOriginalAssets
Type:
type deleteOriginalAssets =
| boolean
| "keep-source-map"
| ((name: string) => boolean);
Default: false
Whether to delete the original assets or not.
webpack.config.js
module.exports = {
plugins: [
new CompressionPlugin({
deleteOriginalAssets: true,
}),
],
};
To exclude sourcemaps from compression:
module.exports = {
plugins: [
new CompressionPlugin({
exclude: /.map$/,
deleteOriginalAssets: "keep-source-map",
}),
],
};
Using a custom function:
module.exports = {
plugins: [
new CompressionPlugin({
exclude: /.map$/,
deleteOriginalAssets: (name) => {
if (/\.js$/.test(name)) {
return false;
}
return true;
},
}),
],
};
Prepare compressed versions of assets using zopfli
library.
[!NOTE]
@gfx/zopfli
require minimum8
version ofnode
.
To begin, you'll need to install @gfx/zopfli
:
$ npm install @gfx/zopfli --save-dev
webpack.config.js
const zopfli = require("@gfx/zopfli");
module.exports = {
plugins: [
new CompressionPlugin({
compressionOptions: {
numiterations: 15,
},
algorithm(input, compressionOptions, callback) {
return zopfli.gzip(input, compressionOptions, callback);
},
}),
],
};
Brotli is a compression algorithm originally developed by Google, and offers compression superior to gzip.
Node 10.16.0 and later has native support for Brotli compression in its zlib module.
We can take advantage of this built-in support for Brotli in Node 10.16.0 and later by just passing in the appropriate algorithm
to the CompressionPlugin:
webpack.config.js
const zlib = require("zlib");
module.exports = {
plugins: [
new CompressionPlugin({
filename: "[path][base].br",
algorithm: "brotliCompress",
test: /\.(js|css|html|svg)$/,
compressionOptions: {
params: {
[zlib.constants.BROTLI_PARAM_QUALITY]: 11,
},
},
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: false,
}),
],
};
[!NOTE] Brotli’s BROTLI_PARAM_QUALITY
option is functionally equivalent to zlib’s level
option.
You can find all Brotli’s options in the relevant part of the zlib module documentation.
webpack.config.js
const zlib = require("zlib");
module.exports = {
plugins: [
new CompressionPlugin({
filename: "[path][base].gz",
algorithm: "gzip",
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
}),
new CompressionPlugin({
filename: "[path][base].br",
algorithm: "brotliCompress",
test: /\.(js|css|html|svg)$/,
compressionOptions: {
params: {
[zlib.constants.BROTLI_PARAM_QUALITY]: 11,
},
},
threshold: 10240,
minRatio: 0.8,
}),
],
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
컨텍스트 는 require('./locale/' + name + '.json')
와 같은 표현식으로 구성된 요청을 의미합니다.
ContextExclusionPlugin
을 사용하면 컨텍스트를 제외할 수 있습니다. 정규 표현식과 일치하는 모든 컨텍스트를 제외하려면 플러그인을 초기화할 때 정규 표현식을 인수로 제공하세요.
webpack.config.js
module.exports = {
plugins: [new webpack.ContextExclusionPlugin(/dont/)],
};
Context는 require('./locale/' + name + '.json')
와 같은 표현식을 통한 요청을 나타냅니다. 이러한 표현식을 만나면, webpack은 디렉터리 ('./locale/'
)와 정규 표현식 (/^.*\.json$/
)을 추론합니다. 컴파일 시 name
을 알 수 없기 때문에 webpack은 모든 파일을 번들에 모듈로 포함합니다.
ContextReplacementPlugin
을 사용하면 추론된 정보를 오버라이드 할 수 있습니다. 플러그인을 구성하는 방법에는 여러 가지가 있습니다.
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만 포함됩니다(자세한 내용은 이 이슈를 참고하세요).
new webpack.ContextReplacementPlugin(
resourceRegExp: RegExp,
newContentCallback: (data) => void
);
newContentCallback
함수에는 ContextModuleFactory
의 data
객체가 제공되며 제공된 객체의 request
속성을 덮어쓸 것으로 예상됩니다.
이 콜백을 사용하여 요청을 새 위치로 동적 리다이렉션할 수 있습니다.
new webpack.ContextReplacementPlugin(/^\.\/locale$/, (context) => {
if (!/\/moment\//.test(context.context)) return;
Object.assign(context, {
regExp: /^\.\/\w+/,
request: '../../locale', // 상대적으로 해결
});
});
newContentResource
및 newContentCreateContextMap
파라미터도 사용할 수 있습니다.
new webpack.ContextReplacementPlugin(
resourceRegExp: RegExp,
newContentResource: string,
newContentCreateContextMap: object // 런타임-요청(userRequest)을 컴파일-시간-요청(request)으로 매핑
);
이 두 파라미터를 함께 사용하여 보다 대상화된 방식으로 요청을 리다이렉션할 수 있습니다. newContentCreateContextMap
을 사용하면 런타임 요청을 매핑하여 객체 형태로 요청을 컴파일 할 수 있습니다.
new ContextReplacementPlugin(/selector/, './folder', {
'./request': './request',
'./other-request': './new-request',
});
Copies individual files or entire directories, which already exist, to the build directory.
To begin, you'll need to install copy-webpack-plugin
:
npm install copy-webpack-plugin --save-dev
or
yarn add -D copy-webpack-plugin
or
pnpm add -D copy-webpack-plugin
Then add the plugin to your webpack
config. For example:
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
{ from: "other", to: "public" },
],
}),
],
};
[!NOTE]
copy-webpack-plugin
is not designed to copy files generated from the build process; rather, it is to copy files that already exist in the source tree, as part of the build process.
[!NOTE]
If you want
webpack-dev-server
to write files to the output directory during development, you can force it with thewriteToDisk
option or thewrite-file-webpack-plugin
.
[!NOTE]
You can get the original source filename from Asset Objects.
The plugin's signature:
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
"path/to/source", // absolute or relative, files/directories/globs - see below for examples
],
options: {
concurrency: 100,
},
}),
],
};
Patterns
from
to
context
globOptions
filter
toType
force
priority
transform
transformAll
noErrorOnMissing
info
from
Type:
type from = string;
Default: undefined
Glob or path from where we copy files.
Globs accept fast-glob pattern-syntax.
Glob can only be a string
.
[!WARNING]
Don't use directly
\\
infrom
option if it is aglob
(i.epath\to\file.ext
) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/
.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
"relative/path/to/file.ext",
"relative/path/to/dir",
path.resolve(__dirname, "src", "file.ext"),
path.resolve(__dirname, "src", "dir"),
"**/*",
{
from: "**/*",
},
// If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`
path.posix.join(
path.resolve(__dirname, "src").replace(/\\/g, "/"),
"*.txt",
),
],
}),
],
};
For windows
If you define from
as absolute file path or absolute folder path on Windows
, you can use windows path segment (\\
)
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, "file.txt"),
},
],
}),
],
};
But you should always use forward-slashes in glob
expressions
See fast-glob manual.
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
// If absolute path is a `glob` we replace backslashes with forward slashes, because only forward slashes can be used in the `glob`
from: path.posix.join(
path.resolve(__dirname, "fixtures").replace(/\\/g, "/"),
"*.txt",
),
},
],
}),
],
};
The context
behaves differently depending on what the from
is (glob
, file
or dir
).
More examples
to
Type:
type to =
| string
| ((pathData: { context: string; absoluteFilename?: string }) => string);
Default: compiler.options.output
string
Output path.
[!WARNING]
Don't use directly
\\
into
(i.epath\to\dest
) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/
orpath
methods.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "**/*",
to: "relative/path/to/dest/",
},
{
from: "**/*",
to: "/absolute/path/to/dest/",
},
{
from: "**/*",
to: "[path][name].[contenthash][ext]",
},
],
}),
],
};
function
Allows to modify the writing path.
[!WARNING]
Don't return directly
\\
into
(i.epath\to\newFile
) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/
orpath
methods.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to({ context, absoluteFilename }) {
return "dest/newPath/[name][ext]";
},
},
],
}),
],
};
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to({ context, absoluteFilename }) {
return Promise.resolve("dest/newPath/[name][ext]");
},
},
],
}),
],
};
context
Type:
type context = string;
Default: options.context|compiler.options.context
A path to be (1) prepended to from
and (2) removed from the start of the result path(s).
[!WARNING]
Don't use directly
\\
incontext
(i.epath\to\context
) option because on UNIX the backslash is a valid character inside a path component, i.e., it's not a separator. On Windows, the forward slash and the backward slash are both separators. Instead please use/
orpath
methods.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.txt",
to: "dest/",
context: "app/",
},
],
}),
],
};
context
can be an absolute path or a relative path. If it is a relative path, then it will be converted to an absolute path based on compiler.options.context
.
context
should be explicitly set only when from
contains a glob. Otherwise, context
is automatically set, based on whether from
is a file or a directory:
If from
is a file, then context
is its directory. The result path will be the filename alone.
If from
is a directory, then context
equals from
. The result paths will be the paths of the directory's contents (including nested contents), relative to the directory.
The use of context
is illustrated by these examples
.
globOptions
[!WARNING]
The onlyDirectories does not work because the plugin is designed to copy files.
Type:
type globOptions = import("globby").Options;
Default: undefined
Allows to configure the glob pattern matching library used by the plugin. See the list of supported options To exclude files from the selection, you should use globOptions.ignore option
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "public/**/*",
globOptions: {
dot: true,
gitignore: true,
ignore: ["**/file.*", "**/ignored-directory/**"],
},
},
],
}),
],
};
filter
Type:
type filter = (filepath: string) => boolean;
Default: undefined
[!NOTE]
To ignore files by path please use the
globOptions.ignore
option.
webpack.config.js
const fs = require("fs").promise;
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "public/**/*",
filter: async (resourcePath) => {
const data = await fs.promises.readFile(resourcePath);
const content = data.toString();
if (content === "my-custom-content") {
return false;
}
return true;
},
},
],
}),
],
};
toType
Type:
type toType = "dir" | "file" | "template";
Default: undefined
Determinate what is to
option - directory, file or template.
Sometimes it is hard to say what is to
, example path/to/dir-with.ext
.
If you want to copy files in directory you need use dir
option.
We try to automatically determine the type
so you most likely do not need this option.
Name | Type | Default | Description |
---|---|---|---|
'dir' | string | undefined | If to has no extension or ends on '/' |
'file' | string | undefined | If to is not a directory and is not a template |
'template' | string | undefined | If to contains a template pattern |
'dir'
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "path/to/file.txt",
to: "directory/with/extension.ext",
toType: "dir",
},
],
}),
],
};
'file'
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "path/to/file.txt",
to: "file/without/extension",
toType: "file",
},
],
}),
],
};
'template'
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/",
to: "dest/[name].[contenthash][ext]",
toType: "template",
},
],
}),
],
};
force
Type:
type force = boolean;
Default: false
Overwrites files already in compilation.assets
(usually added by other plugins/loaders).
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/**/*",
to: "dest/",
force: true,
},
],
}),
],
};
priority
Type:
type priority = number;
Default: 0
Allows to specify the priority of copying files with the same destination name.
Files for patterns with higher priority will be copied later.
To overwrite files, the force
option must be enabled.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
// Copied second and will overwrite "dir_2/file.txt"
{
from: "dir_1/file.txt",
to: "newfile.txt",
force: true,
priority: 10,
},
// Copied first
{
from: "dir_2/file.txt",
to: "newfile.txt",
priority: 5,
},
],
}),
],
};
transform
Type:
type transform =
| {
transformer: (input: string, absoluteFilename: string) => string | Buffer;
cache?: boolean | TransformerCacheObject | undefined;
}
| ((input: string, absoluteFilename: string) => string | Buffer);
Default: undefined
Allows to modify the file contents.
function
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
// The `content` argument is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
// The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied
transform(content, absoluteFrom) {
return optimize(content);
},
},
],
}),
],
};
object
Name | Default | Description |
---|---|---|
transformer | undefined | Allows to modify the file contents. |
cache | false | Enable transform caching. You can use transform: { cache: { key: 'my-cache-key' } } to invalidate the cache. |
transformer
Type:
type transformer = (input: string, absoluteFilename: string) => string;
Default: undefined
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
// The `content` argument is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
// The `absoluteFrom` argument is a `String`, it is absolute path from where the file is being copied
transform: {
transformer(content, absoluteFrom) {
return optimize(content);
},
},
},
],
}),
],
};
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform: {
transformer(content, path) {
return Promise.resolve(optimize(content));
},
},
},
],
}),
],
};
cache
Type:
type cache =
| boolean
| {
keys: {
[key: string]: any;
};
}
| {
keys: (
defaultCacheKeys: {
[key: string]: any;
},
absoluteFilename: string,
) => Promise<{
[key: string]: any;
}>;
}
| undefined;
Default: false
webpack.config.js
Enable/disable and configure caching.
Default path to cache directory: node_modules/.cache/copy-webpack-plugin
.
boolean
Enables/Disable transform
caching.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform: {
transformer(content, path) {
return optimize(content);
},
cache: true,
},
},
],
}),
],
};
object
Enables transform
caching and setup invalidation keys.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform: {
transformer(content, path) {
return optimize(content);
},
cache: {
keys: {
// May be useful for invalidating cache based on external values
// For example, you can invalid cache based on `process.version` - { node: process.version }
key: "value",
},
},
},
},
],
}),
],
};
You can setup invalidation keys using a function.
Simple function:
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform: {
transformer(content, path) {
return optimize(content);
},
cache: {
keys: (defaultCacheKeys, absoluteFrom) => {
const keys = getCustomCacheInvalidationKeysSync();
return {
...defaultCacheKeys,
keys,
};
},
},
},
},
],
}),
],
};
Async function:
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/*.png",
to: "dest/",
transform: {
transformer(content, path) {
return optimize(content);
},
cache: {
keys: async (defaultCacheKeys, absoluteFrom) => {
const keys = await getCustomCacheInvalidationKeysAsync();
return {
...defaultCacheKeys,
keys,
};
},
},
},
},
],
}),
],
};
transformAll
Type:
type transformAll = (
data: {
data: Buffer;
sourceFilename: string;
absoluteFilename: string;
}[],
) => any;
Default: undefined
Allows you to modify the contents of multiple files and save the result to one file.
[!NOTE]
The
to
option must be specified and point to a file. It is allowed to use only[contenthash]
and[fullhash]
template strings.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/**/*.txt",
to: "dest/file.txt",
// The `assets` argument is an assets array for the pattern.from ("src/**/*.txt")
transformAll(assets) {
const result = assets.reduce((accumulator, asset) => {
// The asset content can be obtained from `asset.source` using `source` method.
// The asset content is a [`Buffer`](https://nodejs.org/api/buffer.html) object, it could be converted to a `String` to be processed using `content.toString()`
const content = asset.data;
accumulator = `${accumulator}${content}\n`;
return accumulator;
}, "");
return result;
},
},
],
}),
],
};
noErrorOnMissing
Type:
type noErrorOnMissing = boolean;
Default: false
Doesn't generate an error on missing file(s).
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, "missing-file.txt"),
noErrorOnMissing: true,
},
],
}),
],
};
info
Type:
type info =
| Record<string, any>
| ((item: {
absoluteFilename: string;
sourceFilename: string;
filename: string;
toType: ToType;
}) => Record<string, any>);
Default: undefined
Allows to add assets info.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
"relative/path/to/file.ext",
{
from: "**/*",
// Terser skip this file for minimization
info: { minimized: true },
},
],
}),
],
};
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
"relative/path/to/file.ext",
{
from: "**/*",
// Terser skip this file for minimization
info: (file) => ({ minimized: true }),
},
],
}),
],
};
concurrency
type:
type concurrency = number;
default: 100
limits the number of simultaneous requests to fs
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [...patterns],
options: { concurrency: 50 },
}),
],
};
from
(glob
, file
or dir
).Take for example the following file structure:
src/directory-nested/deep-nested/deepnested-file.txt
src/directory-nested/nested-file.txt
Everything that you specify in from
will be included in the result:
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/directory-nested/**/*",
},
],
}),
],
};
Result:
src/directory-nested/deep-nested/deepnested-file.txt,
src/directory-nested/nested-file.txt
If you don't want the result paths to start with src/directory-nested/
, then you should move src/directory-nested/
to context
, such that only the glob pattern **/*
remains in from
:
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "**/*",
context: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
};
Result:
deep-nested/deepnested-file.txt,
nested-file.txt
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
};
Result:
deep-nested/deepnested-file.txt,
nested-file.txt
Technically, this is **/*
with a predefined context equal to the specified directory.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "**/*",
context: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
};
Result:
deep-nested/deepnested-file.txt,
nested-file.txt
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(
__dirname,
"src",
"directory-nested",
"nested-file.txt",
),
},
],
}),
],
};
Result:
nested-file.txt
Technically, this is a filename with a predefined context equal to path.dirname(pathToFile)
.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "nested-file.txt",
context: path.resolve(__dirname, "src", "directory-nested"),
},
],
}),
],
};
Result:
nested-file.txt
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.posix.join(
path.resolve(__dirname, "src").replace(/\\/g, "/"),
"**/*",
),
globOptions: {
ignore: [
// Ignore all `txt` files
"**/*.txt",
// Ignore all files in all subdirectories
"**/subdir/**",
],
},
},
],
}),
],
};
Removes all directory references and only copies file names.
[!WARNING]
If files have the same name, the result is non-deterministic.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "src/**/*",
to: "[name][ext]",
},
],
}),
],
};
Result:
file-1.txt
file-2.txt
nested-file.txt
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
// When copying files starting with a dot, must specify the toType option
// toType: "file",
to({ context, absoluteFilename }) {
return `newdirectory/${path.relative(context, absoluteFilename)}`;
},
from: "directory",
},
],
}),
],
};
Result:
"newdirectory/file-1.txt",
"newdirectory/nestedfile.txt",
"newdirectory/nested/deep-nested/deepnested.txt",
"newdirectory/nested/nestedfile.txt",
Useful if you need to simply copy *.js
files to destination "as is" without evaluating and minimizing them using Terser.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
"relative/path/to/file.ext",
{
from: "**/*",
// Terser skip this file for minimization
info: { minimized: true },
},
],
}),
],
};
yarn workspaces
and monorepos
When using yarn workspaces
or monorepos
, relative copy paths from node_modules can be broken due to the way packages are hoisting.
To avoid this, should explicitly specify where to copy the files from using require.resolve
.
webpack.config.js
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: `${path.dirname(
require.resolve(`${moduleName}/package.json`),
)}/target`,
to: "target",
},
],
}),
],
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
This plugin uses cssnano to optimize and minify your CSS.
Just like optimize-css-assets-webpack-plugin but more accurate with source maps and assets using query string, allows caching and works in parallel mode.
To begin, you'll need to install css-minimizer-webpack-plugin
:
npm install css-minimizer-webpack-plugin --save-dev
or
yarn add -D css-minimizer-webpack-plugin
or
pnpm add -D css-minimizer-webpack-plugin
Then add the plugin to your webpack
configuration. For example:
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /.s?css$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
optimization: {
minimizer: [
// For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
// `...`,
new CssMinimizerPlugin(),
],
},
plugins: [new MiniCssExtractPlugin()],
};
This will enable CSS optimization only in production mode.
If you want to run it also in development set the optimization.minimize
option to true
:
webpack.config.js
// [...]
module.exports = {
optimization: {
// [...]
minimize: true,
},
};
And run webpack
via your preferred method.
Works only with source-map
, inline-source-map
, hidden-source-map
and nosources-source-map
values for the devtool
option.
Why? Because CSS support only these source map types.
The plugin respect the devtool
and using the SourceMapDevToolPlugin
plugin.
Using supported devtool
values enable source map generation.
Using SourceMapDevToolPlugin
with enabled the columns
option enables source map generation.
Use source maps to map error message locations to modules (this slows down the compilation).
If you use your own minify
function please read the minify
section for handling source maps correctly.
Name | Type | Default | Description |
---|---|---|---|
test | String|RegExp|Array<String|RegExp> | /\.css(\?.*)?$/i | Test to match files against. |
include | String|RegExp|Array<String|RegExp> | undefined | Files to include. |
exclude | String|RegExp|Array<String|RegExp> | undefined | Files to exclude. |
parallel | Boolean|Number | true | Enable/disable multi-process parallel running. |
minify | Function|Array<Function> | CssMinimizerPlugin.cssnanoMinify | Allows to override default minify function. |
minimizerOptions | Object|Array<Object> | { preset: 'default' } | Cssnano optimisations options. |
warningsFilter | Function<(warning, file, source) -> Boolean> | () => true | Allow to filter css-minimizer warnings. |
test
Type: String|RegExp|Array<String|RegExp>
- default: /\.css(\?.*)?$/i
Test to match files against.
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
test: /\.foo\.css$/i,
}),
],
},
};
include
Type: String|RegExp|Array<String|RegExp>
Default: undefined
Files to include.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
include: /\/includes/,
}),
],
},
};
exclude
Type: String|RegExp|Array<String|RegExp>
Default: undefined
Files to exclude.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
exclude: /\/excludes/,
}),
],
},
};
parallel
Type: Boolean|Number
Default: true
Use multi-process parallel running to improve the build speed.
Default number of concurrent runs: os.cpus().length - 1
.
ℹ️ Parallelization can speed up your build significantly and is therefore highly recommended. If a parallelization is enabled, the packages in
minimizerOptions
must be required via strings (packageName
orrequire.resolve(packageName)
). Read more inminimizerOptions
Boolean
Enable/disable multi-process parallel running.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
parallel: true,
}),
],
},
};
Number
Enable multi-process parallel running and set number of concurrent runs.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
parallel: 4,
}),
],
},
};
minify
Type: Function|Array<Function>
Default: CssMinimizerPlugin.cssnanoMinify
Allows overriding default minify function. By default, plugin uses cssnano package. Useful for using and testing unpublished versions or forks.
Possible options:
CssMinimizerPlugin.cssnanoMinify
CssMinimizerPlugin.cssoMinify
CssMinimizerPlugin.cleanCssMinify
CssMinimizerPlugin.esbuildMinify
CssMinimizerPlugin.lightningCssMinify
(previouslyCssMinimizerPlugin.parcelCssMinify
, the package was renamed, but we keep it for backward compatibility)async (data, inputMap, minimizerOptions) => {return {code: "a{color: red}", map: "...", warnings: [], errors: []}}
[!WARNING]
Always use
require
insideminify
function whenparallel
option enabled.
Function
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
level: {
1: {
roundingPrecision: "all=3,px=5",
},
},
},
minify: CssMinimizerPlugin.cleanCssMinify,
}),
],
},
};
Array
If an array of functions is passed to the minify
option, the minimizerOptions
must also be an array.
The function index in the minify
array corresponds to the options object with the same index in the minimizerOptions
array.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: [
{}, // Options for the first function (CssMinimizerPlugin.cssnanoMinify)
{}, // Options for the second function (CssMinimizerPlugin.cleanCssMinify)
{}, // Options for the third function
],
minify: [
CssMinimizerPlugin.cssnanoMinify,
CssMinimizerPlugin.cleanCssMinify,
async (data, inputMap, minimizerOptions) => {
// To do something
return {
code: `a{color: red}`,
map: `{"version": "3", ...}`,
warnings: [],
errors: [],
};
},
],
}),
],
},
};
minimizerOptions
Type: Object|Array<Object>
Default: { preset: 'default' }
Cssnano optimisations options.
Object
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
"default",
{
discardComments: { removeAll: true },
},
],
},
}),
],
},
};
Array
The function index in the minify
array corresponds to the options object with the same index in the minimizerOptions
array.
If you use minimizerOptions
like object, all minify
function accept it.
If a parallelization is enabled, the packages in
minimizerOptions
must be required via strings (packageName
orrequire.resolve(packageName)
). In this case, we shouldn't userequire
/import
.
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: require.resolve("cssnano-preset-simple"),
},
}),
],
},
};
processorOptions
(⚠ only cssnano)Type: Object
Default: { from: assetName }
Allows filtering options processoptions
for the cssnano.
The parser
, stringifier
and syntax
can be either a function or a string indicating the module that will be imported.
[!WARNING]
If a function is passed, the
parallel
option must be disabled..
import sugarss from "sugarss";
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
parallel: false,
minimizerOptions: {
processorOptions: {
parser: sugarss,
},
},
}),
],
},
};
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
processorOptions: {
parser: "sugarss",
},
},
}),
],
},
};
warningsFilter
Type: Function<(warning, file, source) -> Boolean>
Default: () => true
Allow filtering css-minimizer warnings (By default cssnano).
Return true
to keep the warning, a falsy value (false
/null
/undefined
) otherwise.
[!WARNING]
The
source
argument will containundefined
if you don't use source maps.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
warningsFilter: (warning, file, source) => {
if (/Dropping unreachable code/i.test(warning)) {
return true;
}
if (/file\.css/i.test(file)) {
return true;
}
if (/source\.css/i.test(source)) {
return true;
}
return false;
},
}),
],
},
};
Don't forget to enable sourceMap
options for all loaders.
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
devtool: "source-map",
module: {
rules: [
{
test: /.s?css$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: "css-loader", options: { sourceMap: true } },
{ loader: "sass-loader", options: { sourceMap: true } },
],
},
],
},
optimization: {
minimizer: [new CssMinimizerPlugin()],
},
plugins: [new MiniCssExtractPlugin()],
};
Remove all comments (including comments starting with /*!
).
module.exports = {
optimization: {
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
"default",
{
discardComments: { removeAll: true },
},
],
},
}),
],
},
};
webpack.config.js
module.exports = {
// Uncomment if you need source maps
// devtool: "source-map",
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.cssoMinify,
// Uncomment this line for options
// minimizerOptions: { restructure: false },
}),
],
},
};
webpack.config.js
module.exports = {
// Uncomment if you need source maps
// devtool: "source-map",
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.cleanCssMinify,
// Uncomment this line for options
// minimizerOptions: { compatibility: 'ie11,-properties.merging' },
}),
],
},
};
webpack.config.js
module.exports = {
// Uncomment if you need source maps
// devtool: "source-map",
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.esbuildMinify,
}),
],
},
};
@parcel/css
webpack.config.js
module.exports = {
// Uncomment if you need source maps
// devtool: "source-map",
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.lightningCssMinify,
// Uncomment this line for options
// minimizerOptions: { targets: { ie: 11 }, drafts: { nesting: true } },
}),
],
},
};
webpack.config.js
module.exports = {
// Uncomment if you need source maps
// devtool: "source-map",
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
minify: CssMinimizerPlugin.swcMinify,
// Uncomment this line for options
// minimizerOptions: {},
}),
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
DefinePlugin
을 사용하면 컴파일 타임에 구성할 수 있는 전역 상수를 만들 수 있습니다. 이는 개발 빌드와 프로덕션 빌드 간에 서로 다른 동작을 하고 싶을 때 유용합니다. 개발 빌드에서 로깅을 수행하지만, 프로덕션 빌드에서는 수행하지 않는 경우 전역 상수를 사용하여 로깅을 수행할지 여부를 결정할 수 있습니다. 이것이 DefinePlugin
가 유용한 이유입니다. 이 플러그인을 설정하고 개발 및 프로덕션 빌드 환경을 잊어버리세요.
new webpack.DefinePlugin({
// Definitions...
});
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');
기능 플래그를 사용하여 프로덕션/개발 빌드 기능을 활성화/비활성화 할 수 있습니다.
new webpack.DefinePlugin({
NICE_FEATURE: JSON.stringify(true),
EXPERIMENTAL_FEATURE: JSON.stringify(false),
});
프로덕션/개발 빌드에서 서로 다른 서비스 URL을 사용할 수 있습니다.
new webpack.DefinePlugin({
SERVICE_URL: JSON.stringify('https://dev.example.com'),
});
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
과 DllReferencePlugin
은 빌드 시간 성능을 크게 향상시키는 방식으로 번들을 분할하는 수단을 제공합니다. "DLL"이라는 용어는 원래 Microsoft에서 도입한 동적 링크 라이브러리를 나타냅니다.
이 플러그인은 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 함수를 노출(전역 범위로 확대)합니다.
이 플러그인은 기본 webpack 설정에서 사용되며, 사전 빌드된 의존성을 require 하기 위해 dll 전용 번들을 참조합니다.
context
: 매니페스트(또는 콘텐츠 프로퍼티)에 있는 요청의 (절대 경로) 컨텍스트extensions
: dll 번들의 모듈을 해결하는데 사용되는 확장입니다(‘유효범위’를 사용할 때만 사용).manifest
: content
및 name
을 포함하는 객체 또는 컴파일 시 로드될 JSON 매니페스트의 절대 경로에 대한 문자열content
(선택): 요청에서 모듈 id 로의 매핑(기본값은 manifest.content
)name
(선택): dll이 노출되는 식별자(기본값은 manifest.name
)(externals
참조)scope
(선택): dll의 콘텐츠에 접근하는데 사용되는 접두사sourceType
(선택): dll이 노출되는 방법(libraryTarget)new webpack.DllReferencePlugin(options);
dll 매니페스트 파일을 참조하여 의존성 이름을 모듈 id에 매핑한 다음, 내부 __webpack_require__
함수를 사용하여 필요에 따라 요청합니다.
이 플러그인은 scoped 와 mapped 두 가지 모드에서 사용할 수 있습니다.
dll의 콘텐츠는 모듈 접두사 아래에서 접근 가능합니다. 즉, scope = 'xyz'
로 dll의 파일 abc
는 require('xyz/abc')
를 통해 접근할 수 있습니다.
dll의 콘텐츠는 현재 디렉터리에 매핑됩니다. 필요한 파일이 dll의 파일과 확인 후 일치하는 경우, dll의 파일이 대신 사용됩니다.
이것은 dll 번들의 모든 파일을 해석한 후 발생하기 때문에 dll 번들의 사용자에 대해 동일한 경로를 사용할 수 있어야 합니다. 즉, dll에 lodash
가 포함되어 있고 abc
파일이 있으면 require('lodash')
및require('./abc')
가 메인 번들로 빌드되지 않고 dll에서 사용됩니다.
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',
});
두 개의 개별 예제 폴더로, 유효범위와 컨텍스트를 보여줍니다.
EnvironmentPlugin
을 사용해 process.env
키에 DefinePlugin
을 간단히 적용할 수 있습니다.
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),
});
또는, 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');
}
다음과 같은 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
(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")
});
This version of eslint-webpack-plugin only works with webpack 5. For the webpack 4, see the 2.x branch.
This plugin uses eslint
to find and fix problems in your JavaScript code
To begin, you'll need to install eslint-webpack-plugin
:
npm install eslint-webpack-plugin --save-dev
or
yarn add -D eslint-webpack-plugin
or
pnpm add -D eslint-webpack-plugin
[!NOTE]
You also need to install
eslint >= 8
from npm, if you haven't already:
npm install eslint --save-dev
or
yarn add -D eslint
or
pnpm add -D eslint
Then add the plugin to your webpack config. For example:
const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
// ...
plugins: [new ESLintPlugin(options)],
// ...
};
You can pass eslint options.
[!NOTE]
The config option you provide will be passed to the
ESLint
class. This is a different set of options than what you'd specify inpackage.json
or.eslintrc
. See the eslint docs for more details.
[!WARNING]
In eslint-webpack-plugin version 1 the options were passed to the now deprecated CLIEngine.
cache
type cache = boolean;
true
The cache is enabled by default to decrease execution time.
cacheLocation
type cacheLocation = string;
node_modules/.cache/eslint-webpack-plugin/.eslintcache
Specify the path to the cache location. Can be a file or a directory.
configType
type configType = 'flat' | 'eslintrc';
eslintrc
Specify the type of configuration to use with ESLint.
eslintrc
is the classic configuration format available in most ESLint versions.flat
is the new format introduced in ESLint 8.21.0.The new configuration format is explained in its own documentation.
This configuration format being considered as experimental, it is not exported in the main ESLint module in ESLint 8. You need to set your
eslintPath
toeslint/use-at-your-own-risk
for this config format to work.
context
type context = string;
compiler.context
A string indicating the root of your files.
eslintPath
type eslintPath = string;
eslint
Path to eslint
instance that will be used for linting. If the eslintPath
is a folder like a official eslint, or specify a formatter
option. now you don't have to install eslint
.
extensions
type extensions = string | Array<string>;
'js'
Specify extensions that should be checked.
exclude
type exclude = string | Array<string>;
'node_modules'
Specify the files and/or directories to exclude. Must be relative to options.context
.
resourceQueryExclude
type resourceQueryExclude = RegExp | Array<RegExp>;
[]
Specify the resource query to exclude.
files
type files = string | Array<string>;
null
Specify directories, files, or globs. Must be relative to options.context
.
Directories are traversed recursively looking for files matching options.extensions
.
File and glob patterns ignore options.extensions
.
fix
type fix = boolean;
false
Will enable ESLint autofix feature.
Be careful: this option will change source files.
formatter
type formatter = string| (
results: Array<import('eslint').ESLint.LintResult>,
data?: import('eslint').ESLint.LintResultData | undefined
) => string
'stylish'
Accepts a function that will have one argument: an array of eslint messages (object). The function must return the output as a string. You can use official eslint formatters.
lintDirtyModulesOnly
type lintDirtyModulesOnly = boolean;
false
Lint only changed files, skip lint on start.
threads
type threads = boolean | number;
false
Will run lint tasks across a thread pool. The pool size is automatic unless you specify a number.
By default the plugin will auto adjust error reporting depending on eslint errors/warnings counts.
You can still force this behavior by using emitError
or emitWarning
options:
emitError
type emitError = boolean;
true
The errors found will always be emitted, to disable set to false
.
emitWarning
type emitWarning = boolean;
true
The warnings found will always be emitted, to disable set to false
.
failOnError
type failOnError = boolean;
true
Will cause the module build to fail if there are any errors, to disable set to false
.
failOnWarning
type failOnWarning = boolean;
false
Will cause the module build to fail if there are any warnings, if set to true
.
quiet
type quiet = boolean;
false
Will process and report errors only and ignore warnings, if set to true
.
outputReport
type outputReport =
| boolean
| {
filePath?: string | undefined;
formatter?:
| (
| string
| ((
results: Array<import('eslint').ESLint.LintResult>,
data?: import('eslint').ESLint.LintResultData | undefined,
) => string)
)
| undefined;
};
false
Write the output of the errors to a file, for example a checkstyle xml file for use for reporting on Jenkins CI.
The filePath
is an absolute path or relative to the webpack config: output.path
.
You can pass in a different formatter
for the output file,
if none is passed in the default/configured formatter will be used.
EvalSourceMapDevToolPlugin을 사용하면 소스맵 생성을 보다 세밀하게 제어할 수 있습니다. 또한 devtool
설정 옵션의 특정한 세팅에 의해 자동으로 활성화됩니다.
new webpack.EvalSourceMapDevToolPlugin(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://
)을 오버라이드 할 수 있습니다.
다음 예시는 EvalSourceMapDevToolPlugin이 흔히 사용되는 사례를 보여줍니다.
다음 코드를 사용하여 설정 옵션 devtool: eval-source-map
을 동등한 커스텀 플러그인 설정으로 바꿀 수 있습니다.
module.exports = {
// ...
devtool: false,
plugins: [new webpack.EvalSourceMapDevToolPlugin({})],
};
다음 코드는 vendor.js
번들에 있는 모든 모듈에 대한 소스맵을 제외합니다.
new webpack.EvalSourceMapDevToolPlugin({
exclude: ['vendor.js'],
});
이 플러그인은 해시가 모듈의 상대 경로를 기반으로 해 모듈 ID로 4개의 문자열이 생성됩니다. 프로덕션에 사용할 것을 권장합니다.
new webpack.ids.HashedModuleIdsPlugin({
// 옵션...
});
이 플러그인은 다음 옵션을 지원합니다:
context
: 이름을 만들기 위한 컨텍스트 디렉터리 (절대 경로).hashFunction
: 사용할 해싱 알고리즘, 기본 값은 'md4'
입니다. Node.JS의 crypto.createHash
의 모든 기능이 지원됩니다.hashDigest
: 해시를 생성할 때 사용할 인코딩, 기본 값은 'base64'
입니다. Node.JS의 hash.digest
의 모든 인코딩이 지원됩니다.hashDigestLength
: 사용할 해시 다이제스트의 접두사 길이, 기본 값은 4
입니다. 생성된 일부 ID는 모듈 ID 충돌을 피하기 위해 여기에서 지정된 것보다 길 수 있습니다.다음은 이 플러그인을 사용하는 방법의 예시입니다:
new webpack.ids.HashedModuleIdsPlugin({
context: __dirname,
hashFunction: 'sha256',
hashDigest: 'hex',
hashDigestLength: 20,
});
HMR로 알려져 있는 Hot Module Replacement을 활성화합니다.
HMR을 활성화하는 것은 간단하며 대부분의 경우 옵션이 필요하지 않습니다.
new webpack.HotModuleReplacementPlugin({
// Options...
});
This plugin can use 3 tools to optimize and minify your HTML:
swc
- very fast Rust-based platform for the Web.html-minifier-terser
(by default) - JavaScript-based HTML minifier.@minify-html/node
- A Rust HTML minifier meticulously optimised for speed and effectiveness, with bindings for other languages.To begin, you'll need to install html-minimizer-webpack-plugin
:
npm install html-minimizer-webpack-plugin --save-dev
or
yarn add -D html-minimizer-webpack-plugin
or
pnpm add -D html-minimizer-webpack-plugin
Additional step: If you want to use @swc/html
you need to install it:
npm install @swc/html --save-dev
or
yarn add -D @swc/html
or
pnpm add -D @swc/html
Additional step: If you want to use @minify-html/node
you need to install it:
npm install @minify-html/node --save-dev
or
yarn add -D @minify-html/node
or
pnpm add -D @minify-html/node
Then add the plugin to your webpack
configuration. For example:
webpack.config.js
const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
type: "asset/resource",
},
],
},
plugins: [
new CopyPlugin({
patterns: [
{
context: path.resolve(__dirname, "dist"),
from: "./src/*.html",
},
],
}),
],
optimization: {
minimize: true,
minimizer: [
// For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
// `...`
// For `html-minifier-terser`:
//
new HtmlMinimizerPlugin(),
// For `@swc/html`:
//
// HTML documents - HTML documents with `Doctype` and `<html>/`<head>`/`<body>` tags
//
// Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L5
//
// new HtmlMinimizerPlugin({
// minify: HtmlMinimizerPlugin.swcMinify,
// minimizerOptions: {}
// })
//
//
// HTML fragments - HTML fragments, i.e. HTML files without doctype or used in `<template>` tags or HTML parts which injects into another HTML parts
//
// Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L38
//
// new HtmlMinimizerPlugin({
// minify: HtmlMinimizerPlugin.swcMinifyFragment,
// minimizerOptions: {}
// })
],
},
};
This will enable HTML optimization only in production mode.
If you want to run it also in development set the optimization.minimize
option to true
.
And run webpack
via your preferred method.
[!NOTE]
Removing and collapsing spaces in the tools differ (by default).
@swc/html
- remove and collapse whitespaces only in safe places (for example - aroundhtml
andbody
elements, inside thehead
element and between metadata elements -<meta>
/script
/link
/etc.)html-minifier-terser
- always collapse multiple whitespaces to 1 space (never remove it entirely), but you can change it usingoptions
@minify-html/node
- please read documentation https://github.com/wilsonzlin/minify-html#whitespace
test
Type:
type test = string | RegExp | Array<string | RegExp>;
Default: /\.html(\?.*)?$/i
Test to match files against.
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
test: /\.foo\.html/i,
}),
],
},
};
include
Type:
type include = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to include.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
include: /\/includes/,
}),
],
},
};
exclude
Type:
type exclude = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to exclude.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
exclude: /\/excludes/,
}),
],
},
};
parallel
Type:
type parallel = undefined | boolean | number;
Default: true
Use multi-process parallel running to improve the build speed.
Default number of concurrent runs: os.cpus().length - 1
.
[!NOTE]
Parallelization can speed up your build significantly and is therefore highly recommended.
boolean
Enable/disable multi-process parallel running.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
parallel: true,
}),
],
},
};
number
Enable multi-process parallel running and set number of concurrent runs.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
parallel: 4,
}),
],
},
};
minify
Type:
type minify =
| ((
data: { [file: string]: string },
minimizerOptions: {
[key: string]: any;
},
) => {
code: string;
errors?: unknown[] | undefined;
warnings?: unknown[] | undefined;
})
| ((
data: { [file: string]: string },
minimizerOptions: {
[key: string]: any;
},
) => {
code: string;
errors?: unknown[] | undefined;
warnings?: unknown[] | undefined;
})[];
Default: HtmlMinimizerPlugin.htmlMinifierTerser
Allows you to override default minify function. By default, plugin uses html-minifier-terser package.
We currently support:
HtmlMinimizerPlugin.swcMinify
(used to compress HTML documents, i.e. with HTML doctype and <html>
/<body>
/<head>
tags)HtmlMinimizerPlugin.swcMinifyFragment
(used to compress HTML fragments, i.e. when you have part of HTML which will be inserted into another HTML parts)HtmlMinimizerPlugin.htmlMinifierTerser
HtmlMinimizerPlugin.minifyHtmlNode
[!NOTE]
The difference between
swcMinify
andswcMinifyFragment
is the error reporting. You will get errors (invalid or broken syntax) if you have them in your HTML document or fragment. Which allows you to see all the errors and problems at the build stage.
Useful for using and testing unpublished versions or forks.
[!WARNING]
Always use
require
insideminify
function whenparallel
option enabled.
function
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minimizerOptions: {
collapseWhitespace: true,
},
minify: (data, minimizerOptions) => {
const htmlMinifier = require("html-minifier-terser");
const [[filename, input]] = Object.entries(data);
return {
code: htmlMinifier.minify(input, minimizerOptions),
warnings: [],
errors: [],
};
},
}),
],
},
};
array
If an array of functions is passed to the minify
option, the minimizerOptions
can be an array or an object.
If minimizerOptions
is array, the function index in the minify
array corresponds to the options object with the same index in the minimizerOptions
array.
If you use minimizerOptions
like object, all minify
function accept it.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minimizerOptions: [
// Options for the first function (HtmlMinimizerPlugin.htmlMinifierTerser)
{
collapseWhitespace: true,
},
// Options for the second function
{},
],
minify: [
HtmlMinimizerPlugin.htmlMinifierTerser,
(data, minimizerOptions) => {
const [[filename, input]] = Object.entries(data);
// To do something
return {
code: `optimised code`,
warnings: [],
errors: [],
};
},
],
}),
],
},
};
minimizerOptions
Type:
type minimizerOptions =
| {
[key: string]: any;
}
| Array<{
[key: string]: any;
}>;
Default: { caseSensitive: true, collapseWhitespace: true, conservativeCollapse: true, keepClosingSlash: true, minifyCSS: true, minifyJS: true, removeComments: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, }
Html-minifier-terser
optimizations options.
object
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minimizerOptions: {
collapseWhitespace: false,
},
}),
],
},
};
array
The function index in the minify
array corresponds to the options object with the same index in the minimizerOptions
array.
If you use minimizerOptions
like object, all minify
function accept it.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minimizerOptions: [
// Options for the first function (HtmlMinimizerPlugin.htmlMinifierTerser)
{
collapseWhitespace: true,
},
// Options for the second function
{},
],
minify: [
HtmlMinimizerPlugin.htmlMinifierTerser,
(data, minimizerOptions) => {
const [[filename, input]] = Object.entries(data);
// To do something
return {
code: `optimised code`,
warnings: [],
errors: [],
};
},
],
}),
],
},
};
swc/html
Available options
.
HTML Documents:
const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
type: "asset/resource",
},
],
},
plugins: [
new CopyPlugin({
patterns: [
{
context: path.resolve(__dirname, "dist"),
from: "./src/*.html",
},
],
}),
],
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minify: HtmlMinimizerPlugin.swcMinify,
minimizerOptions: {
// Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L5
},
}),
],
},
};
HTML Fragments:
const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
type: "asset/resource",
},
],
},
plugins: [
new CopyPlugin({
patterns: [
{
context: path.resolve(__dirname, "dist"),
from: "./src/*.html",
},
],
}),
],
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
test: /\.template\.html$/i,
minify: HtmlMinimizerPlugin.swcMinifyFragment,
minimizerOptions: {
// Options - https://github.com/swc-project/bindings/blob/main/packages/html/index.ts#L38
},
}),
],
},
};
@minify-html/node
Available options
.
HTML Documents:
const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
type: "asset/resource",
},
],
},
plugins: [
new CopyPlugin({
patterns: [
{
context: path.resolve(__dirname, "dist"),
from: "./src/*.html",
},
],
}),
],
optimization: {
minimize: true,
minimizer: [
new HtmlMinimizerPlugin({
minify: HtmlMinimizerPlugin.minifyHtmlNode,
minimizerOptions: {
// Options - https://github.com/wilsonzlin/minify-html#minification
},
}),
],
},
};
You can use multiple HtmlMinimizerPlugin
plugins to compress different files with the different minify
function.
Please take a moment to read our contributing guidelines if you haven't yet done so.
HtmlWebpackPlugin
은 webpack 번들을 제공하는 HTML 파일 생성을 단순화합니다. 이 플러그인은 매번 컴파일에 변경되는 해시로 된 파일 이름을 가진 webpack 번들에 특히 유용합니다. 플러그인이 HTML 파일을 생성하도록 하거나 lodash 템플릿을 사용하여 나만의 템플릿을 제공하거나 나만의 로더를 사용할 수 있습니다.
npm install --save-dev html-webpack-plugin
플러그인은 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>
태그로 포함됩니다.
모든 설정 옵션은 plugin 문서를 참고하세요.
플러그인은 추가 기능을 지원합니다. 목록은 해당 문서를 참고하세요.
IgnorePlugin은 정규 표현식 또는 필터 함수와 일치하는 import
또는 require
호출에 대한 모듈 생성을 방지합니다.
resourceRegExp
: 리소스 테스트를 위한 정규 표현식contextRegExp
: (선택) 컨텍스트 (디렉터리) 테스트를 위한 정규 표현식new webpack.IgnorePlugin({ resourceRegExp, contextRegExp });
checkResource (resource, context)
는 resource
와 context
를 인수로 받는 필터 함수로, 불리언 값을 반환해야 합니다.new webpack.IgnorePlugin({
checkResource(resource) {
// 리소스를 사용합니다
return true | false;
},
});
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 문이 무시됨을 의미합니다.
Plugin and Loader for webpack to optimize (compress) all images using imagemin. Do not worry about size of images, now they are always optimized/compressed.
This plugin can use 4 tools to optimize/generate images:
imagemin
- optimize your images by default, since it is stable and works with all types of imagessquoosh
- while working in experimental mode with .jpg
, .jpeg
, .png
, .webp
, .avif
file types.sharp
- High performance Node.js image processing, the fastest module to resize and compress JPEG, PNG, WebP, AVIF and TIFF images. Uses the libvips library.svgo
- tool for optimizing SVG vector graphics files. Supports only SVG files minification.[!WARNING]
By default we don't install anything
To begin, you'll need to install image-minimizer-webpack-plugin
and image minimizer/generator:
npm install image-minimizer-webpack-plugin imagemin --save-dev
[!WARNING]
imagemin uses plugin to optimize/generate images, so you need to install them too
squoosh
:npm install image-minimizer-webpack-plugin @squoosh/lib --save-dev
npm install image-minimizer-webpack-plugin sharp --save-dev
svgo
:npm install image-minimizer-webpack-plugin svgo --save-dev
Images can be optimized in two modes:
imagemin
[!NOTE]
- imagemin-mozjpeg can be configured in lossless and lossy mode.
- imagemin-svgo can be configured in lossless and lossy mode.
Explore the options to get the best result for you.
Recommended imagemin plugins for lossless optimization
npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo --save-dev
Recommended imagemin plugins for lossy optimization
npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo --save-dev
For imagemin-svgo
v9.0.0+ need use svgo configuration
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
// Lossless optimization with custom option
// Feel free to experiment with options for better result for you
plugins: [
["gifsicle", { interlaced: true }],
["jpegtran", { progressive: true }],
["optipng", { optimizationLevel: 5 }],
// Svgo configuration here https://github.com/svg/svgo#configuration
[
"svgo",
{
plugins: [
{
name: "preset-default",
params: {
overrides: {
removeViewBox: false,
addAttributesToSVGElement: {
params: {
attributes: [
{ xmlns: "http://www.w3.org/2000/svg" },
],
},
},
},
},
},
],
},
],
],
},
},
}),
],
},
};
squoosh
npm install @squoosh/lib --save-dev
Recommended @squoosh/lib
options for lossy optimization
For lossy optimization we recommend using the default settings of @squoosh/lib
package.
The default values and supported file types for each option can be found in the codecs.ts file under codecs.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.squooshMinify,
options: {
// Your options for `squoosh`
},
},
}),
],
},
};
Recommended squoosh
options for lossless optimization
For lossless optimization we recommend using the options listed below in minimizer.options.encodeOptions
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.squooshMinify,
options: {
encodeOptions: {
mozjpeg: {
// That setting might be close to lossless, but it’s not guaranteed
// https://github.com/GoogleChromeLabs/squoosh/issues/85
quality: 100,
},
webp: {
lossless: 1,
},
avif: {
// https://github.com/GoogleChromeLabs/squoosh/blob/dev/codecs/avif/enc/README.md
cqLevel: 0,
},
},
},
},
}),
],
},
};
sharp
npm install sharp --save-dev
Recommended sharp
options for lossy optimization
For lossy optimization we recommend using the default settings of sharp
package.
The default values and supported file types for each option can be found in the sharp documentation.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.sharpMinify,
options: {
encodeOptions: {
// Your options for `sharp`
// https://sharp.pixelplumbing.com/api-output
},
},
},
}),
],
},
};
Recommended sharp
options for lossless optimization
For lossless optimization we recommend using the options listed below in minimizer.options.encodeOptions
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.sharpMinify,
options: {
encodeOptions: {
jpeg: {
// https://sharp.pixelplumbing.com/api-output#jpeg
quality: 100,
},
webp: {
// https://sharp.pixelplumbing.com/api-output#webp
lossless: true,
},
avif: {
// https://sharp.pixelplumbing.com/api-output#avif
lossless: true,
},
// png by default sets the quality to 100%, which is same as lossless
// https://sharp.pixelplumbing.com/api-output#png
png: {},
// gif does not support lossless compression at all
// https://sharp.pixelplumbing.com/api-output#gif
gif: {},
},
},
},
}),
],
},
};
svgo
npm install svgo --save-dev
Recommended svgo
options for optimization
For optimization we recommend using the options listed below in minimizer.options.encodeOptions
.
The default values for plugins can be found in the svgo plugins source code.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(svg)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.svgoMinify,
options: {
encodeOptions: {
// Pass over SVGs multiple times to ensure all optimizations are applied. False by default
multipass: true,
plugins: [
// set of built-in plugins enabled by default
// see: https://github.com/svg/svgo#default-preset
"preset-default",
],
},
},
},
}),
],
},
};
If you want to use loader
or plugin
standalone see sections below, but this is not recommended.
By default, plugin configures loader
(please use the loader
option if you want to disable this behaviour), therefore you should not setup standalone loader when you use a plugin setup.
Loader optimizes or generates images using options, so inlined images via data
URI (i.e. data:
) will be optimized or generated too, not inlined images will be optimized too.
squoosh
and sharp
currently)The plugin supports the following query parameters:
width
/w
- allows you to set the image width
height
/h
- allows you to set the image height
as
- to specify the preset option
Only supported for sharp
currently:
unit
/u
- can be px
or percent
and allows you to resize by a percentage of the image's size.
Examples:
const myImage1 = new URL("image.png?width=150&height=120", import.meta.url);
const myImage2 = new URL("image.png?w=150&h=120", import.meta.url);
// You can omit one of the parameters to auto-scale
const myImage3 = new URL("image.png?w=150", import.meta.url);
// It works with the `preset` query parameter
const myImage4 = new URL("image.png?as=webp&w=150&h=120", import.meta.url);
// You can use `auto` to reset `width` or `height` from the `preset` option
const myImage5 = new URL("image.png?as=webp&w=150&h=auto", import.meta.url);
// You can use `unit` to get the non-retina resize of images that are retina sized
const myImage6 = new URL("image.png?width=50&unit=percent", import.meta.url);
.class {
background: url("./image.png?width=150&height=120");
}
<picture>
<source srcset="photo.jpg?as=avif&width=150&height=120" type="image/avif" />
<source srcset="photo.jpg?as=webp&width=150&height=120" type="image/webp" />
<img src="photo.jpg?width=150&height=120" alt="photo" />
</picture>
[!NOTE]
You need to setup
avif
andwebp
presets, example for webp.
In your webpack.config.js
, add the ImageMinimizerPlugin.loader
and specify the asset modules options (if you use images in import
):
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
// We recommend using only for the "production" mode
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: ImageMinimizerPlugin.loader,
enforce: "pre",
options: {
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
},
},
],
},
],
},
};
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
// You need this, if you are using `import file from "file.ext"`, for `new URL(...)` syntax you don't need it
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
],
},
optimization: {
minimizer: [
// Extend default minimizer, i.e. `terser-webpack-plugin` for JS
"...",
// We recommend using only for the "production" mode
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
// Disable `loader`
loader: false,
}),
],
},
};
test
Type:
type test = string | RegExp | Array<string | RegExp>;
Default: /\.(jpe?g\|png\|gif\|tif\|webp\|svg\|avif)\$/i
Test to match files against.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
}),
],
},
};
include
Type:
type include = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to include.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
include: /\/includes/,
}),
],
},
};
exclude
Type:
type exclude = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to exclude.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
exclude: /\/excludes/,
}),
],
},
};
minimizer
Type:
type minimizer =
| {
implementation: (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
options?:
| {
[key: string]: any;
}
| undefined;
filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
filename?:
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
}
| Array<{
implementation: (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
options?:
| {
[key: string]: any;
}
| undefined;
filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
filename?:
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
}>;
Default: undefined
Allows to setup default minify function.
ImageMinimizerPlugin.imageminMinify
ImageMinimizerPlugin.squooshMinify
ImageMinimizerPlugin.sharpMinify
ImageMinimizerPlugin.svgoMinify
imagemin
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
// Implementation
implementation: ImageMinimizerPlugin.imageminMinify,
// Options
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
More information and examples here.
squoosh
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
// Implementation
implementation: ImageMinimizerPlugin.squooshMinify,
// Options
options: {
encodeOptions: {
mozjpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
More information and examples here.
sharp
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
// Implementation
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
More information and examples here.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: async (original, options) => {
const inputExt = path.extname(original.filename).toLowerCase();
if (inputExt !== ".xxx") {
// Return `null` if the implementation does not support this file type
return null;
}
let result;
try {
result = await minifyAndReturnBuffer(original.data);
} catch (error) {
// Store error and return `null` if there was an error
original.errors.push(error);
return null;
}
return {
filename: original.filename,
data: result,
warnings: [...original.warnings],
errors: [...original.errors],
info: {
...original.info,
// Please always set it to prevent double minification
minimized: true,
// Optional
minimizedBy: ["custom-name-of-minimication"],
},
};
},
options: {
// Custom options
},
},
}),
],
},
};
Allows to setup multiple minimizers.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: [
{
// `sharp` will handle all bitmap formats (JPG, PNG, GIF, ...)
implementation: ImageMinimizerPlugin.sharpMinify,
// exclude SVG if implementation support it. Not required for `sharp`.
// filter: (source, sourcePath) => !(/\.(svg)$/i.test(sourcePath)),
options: {
encodeOptions: {
// Your options for `sharp`
// https://sharp.pixelplumbing.com/api-output
},
},
},
{
// `svgo` will handle vector images (SVG)
implementation: ImageMinimizerPlugin.svgoMinify,
options: {
encodeOptions: {
// Pass over SVGs multiple times to ensure all optimizations are applied. False by default
multipass: true,
plugins: [
// set of built-in plugins enabled by default
// see: https://github.com/svg/svgo#default-preset
"preset-default",
],
},
},
},
],
}),
],
},
};
implementation
Type:
type implementation = (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?: BasicTransformerOptions<T>,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
Default: undefined
Configure the default implementation
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
// Implementation
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
options
Type:
type options = {
[key: string]: any;
};
Default: undefined
Options for the implementation
option (i.e. options for imagemin
/squoosh
/sharp
/custom implementation).
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
filter
Type:
type filter = (source: Buffer, sourcePath: string) => boolean | undefined;
Default: () => true
Allows filtering of images for optimization/generation.
Return true
to optimize the image, false
otherwise.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
filter: (source, sourcePath) => {
// The `source` argument is a `Buffer` of source file
// The `sourcePath` argument is an absolute path to source
if (source.byteLength < 8192) {
return false;
}
return true;
},
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
filename
Type:
type filename =
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
Default: undefined
Allows to set the filename.
Supported values see in webpack template strings
, File-level
section.
We also support [width]
and [height]
placeholders (only sharp
and squoosh
).
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
filename: "optimized-[name][ext]",
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
Example function
usage:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
filename: () => "optimized-[name][ext]",
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
}),
],
},
};
generator
Type:
type generator = Array<{
implementation: (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
options?:
| {
[key: string]: any;
}
| undefined;
filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
filename?:
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
preset?: string | undefined;
type?: "import" | "asset" | undefined;
}>;
Default: undefined
Allow to setup default generators.
Useful if you need generate webp
/avif
/etc from other formats.
[!WARNING]
If no generator was found for the image (i.e. no
?as=webp
was found in query params), theminimizer
option will be used. Therefore, it is recommended to configure generator outputs optimized image.
[!WARNING]
The option will not work if you disable
loader
(i.e. set theloader
option tofalse
).
ImageMinimizerPlugin.imageminGenerate
ImageMinimizerPlugin.squooshGenerate
ImageMinimizerPlugin.sharpGenerate
imagemin
Example webp
generator:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
// Please specify only one plugin here, multiple plugins will not work
plugins: ["imagemin-webp"],
},
},
],
}),
],
},
};
squoosh
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.squooshGenerate,
options: {
encodeOptions: {
// Please specify only one codec here, multiple codecs will not work
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
sharp
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
// Please specify only one codec here, multiple codecs will not work
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
Now you can generate the new image using:
// Old approach for getting URL
import webp from "./file.jpg?as=webp";
// Assets modules
console.log(new URL("./file.jpg?as=webp"));
div {
background: url("./file.jpg?as=webp");
}
You can use ?as=webp
in any type of files.
Example multiple generators:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
webp: {
lossless: false,
},
},
},
},
{
// You can apply generator using `?as=avif`, you can use any name and provide more options
preset: "avif",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
avif: {
lossless: false,
},
},
},
},
],
}),
],
},
};
squoosh
and sharp
generator supports more options, for example you can resize an image:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp-100-50`, you can use any name and provide more options
preset: "webp-100-50",
// implementation: ImageMinimizerPlugin.squooshGenerate,
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
resize: {
enabled: true,
width: 100,
height: 50,
},
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
You can find more information here.
For only sharp
currently, you can even generate the non-retina resizes of images:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp-1x`, you can use any name and provide more options
preset: "webp-1x",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
resize: {
enabled: true,
width: 50,
unit: "percent",
},
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
You can use your own generator implementation.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: async (original, options) => {
const inputExt = path.extname(original.filename).toLowerCase();
if (inputExt !== ".xxx") {
// Store error and return `null` if the implementation does not support this file type
original.errors.push(error);
return null;
}
let result;
try {
result = await minifyAndReturnBuffer(original.data);
} catch (error) {
// Store error and return `null` if there was an error
original.errors.push(error);
return null;
}
return {
filename: original.filename,
data: result,
warnings: [...original.warnings],
errors: [...original.errors],
info: {
...original.info,
// Please always set it to prevent double minification
generated: true,
// Optional
generatedBy: ["custom-name-of-minification"],
},
};
},
options: {
// Your options
},
},
],
}),
],
},
};
type
Type:
type type = "import" | "asset" | undefined;
Default: "import"
Allows you to apply the generator for import
or assets from compilation (useful for copied assets).
By default, generators are applying on import
/require
, but sometimes you need to generate new images from other plugins (for example - copy-webpack-plugin
), if you need this, please set asset
value for the type
option.
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
generator: [
{
// Apply generator for copied assets
type: "asset",
// You can use `ImageMinimizerPlugin.squooshGenerate`
// You can use `ImageMinimizerPlugin.sharpGenerate`
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: ["imagemin-webp"],
},
},
],
}),
],
},
plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
preset
Type:
type preset = string | undefined;
Default: undefined
Configure the name of preset, i.e. you can use it in ?as=name
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
// Implementation
implementation: ImageMinimizerPlugin.sharpMinify,
options: {
encodeOptions: {
jpeg: {
quality: 85,
},
},
},
},
],
}),
],
},
};
implementation
Type:
type implementation = (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
Default: undefined
Configure the default implementation
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
// Implementation
implementation: ImageMinimizerPlugin.sharpMinify,
options: {
encodeOptions: {
jpeg: {
quality: 85,
},
},
},
},
],
}),
],
},
};
options
Type:
type options = {
[key: string]: any;
};
Default: undefined
Options for the implementation
option (i.e. options for imagemin
/squoosh
/sharp
/custom implementation).
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
],
}),
],
},
};
filter
Type:
type filter = (source: Buffer, sourcePath: string) => boolean;
Default: () => true
Allows filtering of images for optimization/generation.
Return true
to optimize the image, false
otherwise.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
filter: (source, sourcePath) => {
// The `source` argument is a `Buffer` of source file
// The `sourcePath` argument is an absolute path to source
if (source.byteLength < 8192) {
return false;
}
return true;
},
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
],
}),
],
},
};
filename
Type:
type filename =
| string
| ((
pathData: PathData,
assetInfo?: import("webpack").AssetInfo | undefined,
) => string);
Default: undefined
Allows to set the filename.
Supported values see in webpack template strings
, File-level
section.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
filename: "generated-[name][ext]",
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
],
}),
],
},
};
Example of function
usage:
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "name",
filename: () => "generated-[name][ext]",
implementation: ImageMinimizerPlugin.sharpMinify,
// Options
options: {
encodeOptions: {
jpeg: {
quality: 90,
},
},
},
},
],
}),
],
},
};
severityError
Type:
type severityError = string;
Default: 'error'
Allows to choose how errors are displayed.
Сan have the following values:
'off'
- suppresses errors and warnings'warning'
- emit warnings instead errors'error'
- emit errorswebpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
severityError: "warning",
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
loader
Type:
type loader = boolean;
Default: true
Automatically adding built-in loader
, used to optimize/generate images.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
loader: false,
// `generator` will not work in this case
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
concurrency
Type:
type concurrency = number;
Default: Math.max(1, os.cpus().length - 1)
Maximum number of concurrency optimization processes in one time.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
concurrency: 3,
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
deleteOriginalAssets
Type:
type deleteOriginalAssets = boolean;
Default: true
Allows removing original assets after optimization.
Please use this option if you are set the filename
option for the minimizer
option, disable loader: false
and want to keep optimized and not optimized assets.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
// Disable loader
loader: false,
// Allows to keep original asset and minimized assets with different filenames
deleteOriginalAssets: false,
minimizer: {
filename: "[path][name].webp",
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
}),
],
},
};
minimizer
Type:
type minimizer =
| {
implementation: (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
options?:
| {
[key: string]: any;
}
| undefined;
filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
filename?:
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
}
| Array<{
implementation: (
original: {
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
},
options?:
| {
[key: string]: any;
}
| undefined,
) => Promise<{
filename: string;
data: Buffer;
warnings: Array<Error>;
errors: Array<Error>;
info: import("webpack").AssetInfo;
}> & {
setup?: (() => void) | undefined;
teardown?: (() => void) | undefined;
};
options?:
| {
[key: string]: any;
}
| undefined;
filter?: (source: Buffer, sourcePath: string) => boolean | undefined;
filename?:
| string
| ((
pathData: {
filename?: string | undefined;
},
assetInfo?: import("webpack").AssetInfo | undefined,
) => string)
| undefined;
}>;
Default: undefined
Allows to setup default minimizer.
imagemin
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: ImageMinimizerPlugin.loader,
enforce: "pre",
options: {
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
},
},
],
},
};
For more information and supported options please read here.
generator
Type:
type generator = Array<{
implementation: TransformerFunction<T>;
options?: BasicTransformerOptions<T>;
filter?: FilterFn | undefined;
filename?: string | FilenameFn | undefined;
preset?: string | undefined;
type?: "import" | "asset" | undefined;
}>;
Default: undefined
Allow to setup default generators.
Useful if you need generate webp
/avif
/etc from other formats.
imagemin
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: ImageMinimizerPlugin.loader,
enforce: "pre",
options: {
generator: [
{
preset: "webp",
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: ["imagemin-webp"],
},
},
],
},
},
],
},
};
For more information and supported options please read here.
severityError
Type:
type severityError = string;
Default: 'error'
Allows to choose how errors are displayed.
Сan have the following values:
'off'
- suppresses errors and warnings'warning'
- emit warnings instead errors'error'
- emit errorswebpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: ImageMinimizerPlugin.loader,
options: {
severityError: "warning",
minimizerOptions: {
plugins: ["gifsicle"],
},
},
},
],
},
],
},
};
imageminNormalizeConfig(config)
The function normalizes configuration (converts plugins names and options to Function
s) for using in imagemin
package directly.
const imagemin = require("imagemin");
const { imageminNormalizeConfig } = require("image-minimizer-webpack-plugin");
/*
console.log(imageminConfig);
=>
{
plugins: [Function, Function],
pluginsMeta: [
{ name: "imagemin-jpegtran", version: "x.x.x", options: {} },
{ name: "imagemin-pngquant", version: "x.x.x", options: { quality: [0.6, 0.8] }
]
}
*/
(async () => {
const imageminConfig = await imageminNormalizeConfig({
plugins: ["jpegtran", ["pngquant", { quality: [0.6, 0.8] }]],
});
const files = await imagemin(["images/*.{jpg,png}"], {
destination: "build/images",
plugins: imageminConfig.plugins,
});
console.log(files);
// => [{data: <Buffer 89 50 4e …>, path: 'build/images/foo.jpg'}, …]
})();
You can use difference options (like progressive
/interlaced
/etc.) based on image size (example - don't do progressive transformation for small images).
What is progressive
image? Answer here
.
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [["jpegtran", { progressive: true }]],
},
// Only apply this one to files equal to or over 8192 bytes
filter: (source) => {
if (source.byteLength >= 8192) {
return true;
}
return false;
},
},
}),
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [["jpegtran", { progressive: false }]],
},
// Only apply this one to files under 8192
filter: (source) => {
if (source.byteLength < 8192) {
return true;
}
return false;
},
},
}),
],
},
};
webp
imageswebpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: ["imagemin-webp"],
},
},
],
}),
],
},
};
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.squooshMinify,
},
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.squooshGenerate,
options: {
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
webpack.config.js
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.sharpMinify,
},
generator: [
{
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
};
webp
images from copied assetswebpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
],
},
},
generator: [
{
type: "asset",
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: ["imagemin-webp"],
},
},
],
}),
],
},
plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.squooshMinify,
},
generator: [
{
type: "asset",
implementation: ImageMinimizerPlugin.squooshGenerate,
options: {
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.sharpMinify,
},
generator: [
{
type: "asset",
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
webp: {
quality: 90,
},
},
},
},
],
}),
],
},
plugins: [new CopyPlugin({ patterns: ["images/**/*.png"] })],
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
Speed up development by automatically installing & saving dependencies with Webpack.
It is inefficient to Ctrl-C your build script & server just to install a dependency you didn't know you needed until now.
Instead, use require
or import
how you normally would and installation
will happen automatically to install & save missing dependencies while you work!
$ npm install --save-dev install-webpack-plugin
In your webpack.config.js
:
plugins: [
new InstallPlugin()
],
This is equivalent to:
plugins: [
new InstallPlugin({
dependencies: {
peer: true,
},
packageManager: {
type: this.getDefaultPackageManager(),
options: {
dev: false,
quiet: false,
},
},
prompt: true,
});
],
Type: Object
Dependencies related options.
Type: Boolean
Default: true
Install missing peer dependencies.
plugins: [
new InstallPlugin({
dependencies: {
peer: true,
}
}),
],
Type: 'npm' | 'yarn' | 'pnpm' | Object | Function
Package manager to use for installing dependencies.
plugins: [
new InstallPlugin({
packageManager: 'yarn'
},
}),
],
You can provide a Function
to the packageManager
to make it dynamic:
plugins: [
new InstallPlugin({
packageManager: function(module, path) {
return [
"babel-preset-react-hmre",
"webpack-dev-middleware",
"webpack-hot-middleware",
].indexOf(module) !== -1;
},
}),
],
Type: 'npm' | 'yarn' | 'pnpm'
Name of package manager to use for installing dependencies.
Type: Object
Package manager related options.
Type: Array
Provide custom arguments to use with package manager.
plugins: [
new InstallPlugin({
packageManager: {
type: 'npm',
options: {
arguments: ['--ignore-scripts']
}
}
},
}),
],
Type: Boolean
Default: false
Install as development dependencies.
plugins: [
new InstallPlugin({
packageManager: {
type: 'npm',
options: {
dev: true,
}
}
},
}),
],
Type: Boolean
Default: false
Reduce the amount of console logging.
plugins: [
new InstallPlugin({
packageManager: {
type: 'npm',
options: {
quiet: true,
}
}
},
}),
],
Type: Boolean
Default: true
Show a prompt to confirm installation.
plugins: [
new InstallPlugin({
prompt: true,
},
}),
],
^v5.0.0
..babelrc
plugins & presets.require
, import
)@cycle/dom
)lodash.capitalize
)@import "~bootstrap"
)babel-loader
, file-loader
, etc.)require("bundle?lazy!./App"
)peerDependencies
.
(e.g. @cycle/core
will automatically install rx@*
)resolve.alias
& resolve.root
configuration.
(e.g. require("react")
can alias to react-lite
)Please take a moment to read our contributing guidelines if you haven't yet done so.
Webpack 내부적으로 사용하는 플러그인의 목록입니다.
내부 플러그인의 범주:
컴파일러의 환경에 영향을 주는 플러그인입니다.
webpack.node.NodeEnvironmentPlugin()
컴파일러에 Node.js 스타일의 파일 시스템을 적용합니다.
컴파일러에 영향을 주는 플러그인입니다.
MemoryCachePlugin()
모듈이 메모리에 캐시되는 컴파일러에 캐시를 추가합니다.
ProgressPlugin(handler)
컴파일러에 훅을 하여 진행 정보를 추출합니다. handler
는 function(percentage, message)
라는 서명이 있어야 합니다. Percentage는 0과 1 사이의 값으로 불립니다. 0은 시작, 1은 끝을 나타냅니다.
RecordIdsPlugin()
레코드로부터 청크 아이디와 모듈을 저장하고 복원합니다.
컴파일에 엔트리 청크를 포함하는 플러그인입니다.
EntryPlugin(context, entry, options)
컴파일에 엔트리 청크를 추가합니다. 청크의 이름은 options.name
이고 오직 하나의 모듈만 포함합니다(의존성 추가). 모듈은 context
(절대 경로)의 entry
에서 확인됩니다.
PrefetchPlugin(context, request)
병렬 컴파일을 더 사용하기 위해서 의존성과 request
를 프리페치합니다. 어떤 청크도 생성되지 않습니다. 모듈은 context
(절대 경로)의 request
에서 확인됩니다.
JsonpTemplatePlugin(options)
청크는 JSONP-calls로 래핑되어 있습니다. 로딩 알고리즘은 엔트리 청크에 포함이 됩니다. <script>
태그를 추가함으로써 청크를 로드합니다.
options
는 출력 옵션입니다.
options.jsonpFunction
은 JSONP 함수입니다.
options.publicPath
는 청크를 로딩하기 위한 경로로 사용됩니다.
options.chunkFilename
는 청크가 예상되는 파일 이름 이름입니다.
node/NodeTemplatePlugin(options)
청크는 번들 모듈을 내보내는 Node.js 모듈로 래핑되어 있습니다. 엔트리 청크는 청크를 요구함으로써 로드됩니다.
options
는 출력 옵션입니다.
options.chunkFilename
는 청크를 로딩하기 위한 경로로 사용됩니다.
LibraryTemplatePlugin(name, target)
엔트리 청크들은 type
유형의 name
라이브러리로부터 꾸며집니다.
webworker/WebWorkerTemplatePlugin(options)
청크는 importScripts
에 의해 로드됩니다. 그렇지 않다면 JsonpTemplatePlugin
과 비슷합니다.
options
은 출력 옵션입니다.
// @sourceURL
로 주석이 달린 eval
로 각각의 모듈을 래핑함으로써 모듈 템플릿을 꾸밉니다.
SourceMapDevToolPlugin(sourceMapFilename, sourceMappingURLComment, moduleFilenameTemplate, fallbackModuleFilenameTemplate)
각 청크에 대한 소스맵을 생성함으로써 템플릿들을 꾸밉니다.
sourceMapFilename
은 소스맵의 파일 이름 템플릿입니다. [hash]
, [name]
, [id]
, [file]
과 [filebase]
는 교체되었습니다. 만약에 인자가 없으면, 소스맵은 DataUrl로 인라인 될 것입니다.
HotModuleReplacementPlugin(options)
Hot module replacement 대한 지원을 추가합니다. 런타임 코드를 추가한 템플릿을 꾸밉니다. `module.hot' API를 추가합니다.
options.hotUpdateChunkFilename
은 hot 업데이트 청크 파일 이름입니다.
options.hotUpdateMainFilename
은 hot 업데이트 매니페스트 파일 이름입니다.
options.hotUpdateFunction
는 hot 업데이트의 JSON 함수 이름입니다.
모듈의 소스 코드에 영향을 미치는 플러그인입니다.
webpack_public_path, webpack_require, webpack_modules 과 webpack_chunk_load에 접근할 수 있도록 설정합니다. require.valueOf
와 require.onError
가 다른 플러그인으로 처리되지 않도록 합니다.
현재는 쓸모가 없습니다. 다른 모듈 로더과의 호환성을 보장합니다.
파서에 의해 발사된 훅을 사용함으로써 dead branch를 추가로 제거를 가능하게 하려고 if (...)
문과 삼항 연산자를 평가하여 true/false
로 바꾸려고 시도합니다.
프로덕션 모드에는 dead branch와 관련하여 여러 최적화 들이 있습니다.
Webpack은 조건문을 평가하려고 할 것입니다. 만약 성공한다면 dead branch가 제거됩니다. Webpck은 컴파일러가 알지 못하는 한 상수 폴딩을 할 수 없습니다. 다음 예시를 봅시다.
import { calculateTax } from './tax';
const FOO = 1;
if (FOO === 0) {
// dead branch
calculateTax();
}
위의 예시에서, webpack은 branch를 자를 수 없지만, Terser는 할 수 있습니다. 그러나 만약 FOO
가 DefinePlugin 을 사용하면, webpack은 성공할 것입니다.
import { calculateTax } from './tax';
도 제거된다는 점을 언급해야 합니다. 왜냐하면 calculateTax()
호출이 dead branch에 있어 제거되었기 때문입니다.
ProvidePlugin(name, request)
만약에 모듈에서 name
이 사용되는 경우는 require(<request>)
에 의해 로드된 모듈에 의해서 채워집니다.
NodeStuffPlugin(options, context)
Node.js 모듈에서는 일반적으로 사용할 수 있는 항목을 제공합니다.
또한, module
을 사용하는 경우에는 일부의 Node.js 항목으로 채워지도록 합니다.
require.js에서는 일반적으로 사용할 수 있는 항목을 제공합니다.
require[js].config
는 제거됩니다. require.version
은 0.0.0
입니다. requirejs.onError
는 require.onError
에 매핑이 됩니다.
node/NodeSourcePlugin(options)
이 모듈은 Node.js 환경이 아니면 사용할 수 없는 Node.js의 내용을 추가합니다.
사용되는 경우에는 process
, console
, Buffer
와 glo
에 대한 polyfills을 추가해야 합니다.
node/NodeTargetPlugin()
만약 Node.js 환경에서 번들을 실행하는 경우에는 플러그인을 사용해야 합니다.
만약 네이티브 모듈이 번들 되어있더라도 올바르게 로드되도록 보장합니다.
dependencies/AMDPlugin(options)
AMD 스타일의 define
과 require
모듈을 제공합니다. 또한, require.amd
, define.amd
와 webpack_amd_options## 를 파라미터로 전달된 options
에 바인딩합니다.
dependencies/CommonJsPlugin
CommonJs 스타일의 require
모듈을 제공합니다.
dependencies/RequireContextPlugin(modulesDirectories, extensions)
require.content
를 제공합니다. modulesDirectories
와 extensions
파라미터는 파일에 대한 요청을 대체할 수 있는 것을 찾는 데 사용됩니다. 리졸버에 제공하는 것과 동일한 배열을 제공하는 것이 유용합니다.
dependencies/RequireEnsurePlugin()
require.ensure
를 제공합니다.
dependencies/RequireIncludePlugin()
require.include
를 제공합니다.
DefinePlugin(definitions)
식별자에 대해 상수를 정의합니다.
definitions
은 객체입니다.
webpack.optimize
네임스페이스 아래의 모든 플러그인은 mode
가 'none'
으로 설정된 경우에만 사용해야 합니다. 그렇지 않다면 플러그인은 두 번 적용되어야 합니다.
optimize/LimitChunkCountPlugin(options)
병합 청크의 제한된 청크 수는 `options.maxChunks'보다 작습니다.
각 청크에 대한 오버헤드는 options.chunkOverhead
또는 기본값인 10000에 의해 제공됩니다. 엔트리 청크의 크기는 options.entryChunkMultiplicator
(또는 10)에 의해 곱해집니다.
전체적인 크기를 가장 많이 줄인 청크가 첫 번째로 병합됩니다. 만약 여러 조합이 같으면 병합된 크기가 작은 것이 선택됩니다.
optimize/MergeDuplicateChunksPlugin()
같은 모듈의 청크가 병합됩니다.
optimize/RemoveEmptyChunksPlugin()
모든 부모 청크에 포함된 모듈은 청크로부터 제거됩니다.
optimize/MinChunkSizePlugin(minChunkSize)
-
각 청크의 최소 크기가 minChunkSize
가 될 때까지 청크를 병합합니다.
ModuleConcatenationPlugin page에 대한 구체적인 내용을 확인해보세요.
optimize/FlagIncludedChunksPlugin()
청크에 포함된 청크의 청크 아이디를 추가합니다. 불필요한 청크 로드를 제거할 수 있습니다.
optimize/RealContentHashPlugin()
optimization.realContentHash
옵션이 활성화 될 때, webpack은 내부적으로 RealContentHashPlugin
을 컴파일러에 추가합니다.
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) => {
// 이곳에서 원하는데로 해시를 계산할 수 있습니다.
});
});
This plugin uses JSON.stringify() to minify your JSON.
To begin, you'll need to install json-minimizer-webpack-plugin
:
npm install json-minimizer-webpack-plugin --save-dev
or
yarn add -D json-minimizer-webpack-plugin
or
pnpm add -D json-minimizer-webpack-plugin
Then add the plugin to your webpack
configuration. For example:
webpack.config.js
const JsonMinimizerPlugin = require("json-minimizer-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.json$/i,
type: "asset/resource",
},
],
},
plugins: [
new CopyPlugin({
patterns: [
{
context: path.resolve(__dirname, "dist"),
from: "./src/*.json",
},
],
}),
],
optimization: {
minimize: true,
minimizer: [
// For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
// `...`
new JsonMinimizerPlugin(),
],
},
};
And run webpack
via your preferred method.
test
Type:
type test = string | RegExp | Array<string | RegExp>;
Default: /\.json(\?.*)?$/i
Test to match files against.
module.exports = {
optimization: {
minimize: true,
minimizer: [
new JsonMinimizerPlugin({
test: /\.foo\.json/i,
}),
],
},
};
include
Type:
type include = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to include.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new JsonMinimizerPlugin({
include: /\/includes/,
}),
],
},
};
exclude
Type:
type exclude = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to exclude.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new JsonMinimizerPlugin({
exclude: /\/excludes/,
}),
],
},
};
minimizerOptions
Type:
type minimizerOptions = {
space?: null | string | number;
replacer?: null | Function | Array<string | number>;
};
Default: { replacer: null, space: null }
JSON.stringify()
options.
module.exports = {
optimization: {
minimize: true,
minimizer: [
new JsonMinimizerPlugin({
minimizerOptions: {
space: "\t",
},
}),
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
코드를 작성할 때, 이미 필요한 것을 로드할 많은 코드 분할 지점을 추가했을 것입니다. 컴파일 후에 어떤 청크가 너무 작다는 것을 깨달을 것입니다. 이는 더 큰 HTTP 오버헤드를 만듭니다. LimitChunkCountPlugin
은 청크를 합침으로써 그것들을 후속 처리할 수 있게 해줍니다.
new webpack.optimize.LimitChunkCountPlugin({
// Options...
});
다음의 옵션들이 지원됩니다.
number
청크의 최대 개수를 1
보다 크거나 같도록 제한합니다. 1
을 사용하는 것은 엔트리/메인 청크가 카운트에 포함될 때 추가적인 청크가 더해지는 것을 방지합니다.
webpack.config.js
const webpack = require('webpack');
module.exports = {
// ...
plugins: [
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 5,
}),
],
};
위의 지정된 청크 크기를 유지하는 것은 이 플러그인에서 구현하지 않습니다. MinChunkSizePlugin을 대신 사용하세요.
이 플러그인과 옵션은 CLI를 통해 호출될 수도 있습니다.
webpack --optimize-max-chunks 15
minChunkSize
보다 작은 청크를 병합하여 청크 크기를 설정한 한계 이상으로 유지합니다.
new webpack.optimize.MinChunkSizePlugin({
minChunkSize: 10000, // 최소 문자 수
});
해당 플러그인과 플러그인 옵션은 CLI를 통해서도 실행할 수 있습니다.
webpack --optimize-min-chunk-size 10000
This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps.
It builds on top of a new webpack v5 feature and requires webpack 5 to work.
Compared to the extract-text-webpack-plugin:
To begin, you'll need to install mini-css-extract-plugin
:
npm install --save-dev mini-css-extract-plugin
or
yarn add -D mini-css-extract-plugin
or
pnpm add -D mini-css-extract-plugin
It's recommended to combine mini-css-extract-plugin
with the css-loader
Then add the loader and the plugin to your webpack
config. For example:
style.css
body {
background: green;
}
component.js
import "./style.css";
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
[!WARNING]
Note that if you import CSS from your webpack entrypoint or import styles in the initial chunk,
mini-css-extract-plugin
will not load this CSS into the page. Please usehtml-webpack-plugin
for automatic generationlink
tags or createindex.html
file withlink
tag.
[!WARNING]
Source maps works only for
source-map
/nosources-source-map
/hidden-nosources-source-map
/hidden-source-map
values because CSS only supports source maps with thesourceMappingURL
comment (i.e.//# sourceMappingURL=style.css.map
). If you need setdevtool
to another value you can enable source maps generation for extracted CSS usingsourceMap: true
forcss-loader
.
filename
Type:
type filename =
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
Default: [name].css
This option determines the name of each output CSS file.
Works like output.filename
chunkFilename
Type:
type chunkFilename =
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
Default: based on filename
Specifying
chunkFilename
as afunction
is only available in webpack@5
This option determines the name of non-entry chunk files.
Works like output.chunkFilename
ignoreOrder
Type:
type ignoreOrder = boolean;
Default: false
Remove Order Warnings. See examples below for details.
insert
Type:
type insert = string | ((linkTag: HTMLLinkElement) => void);
Default: document.head.appendChild(linkTag);
Inserts the link
tag at the given position for non-initial (async) CSS chunks
[!WARNING]
Only for non-initial (async) chunks.
By default, the mini-css-extract-plugin
appends styles (<link>
elements) to document.head
of the current window
.
However in some circumstances it might be necessary to have finer control over the append target or even delay link
elements insertion.
For example this is the case when you asynchronously load styles for an application that runs inside of an iframe.
In such cases insert
can be configured to be a function or a custom selector.
If you target an iframe make sure that the parent document has sufficient access rights to reach into the frame document and append elements to it.
string
Allows to setup custom query selector.
A new <link>
element will be inserted after the found item.
webpack.config.js
new MiniCssExtractPlugin({
insert: "#some-element",
});
A new <link>
element will be inserted after the element with id some-element
.
function
Allows to override default behavior and insert styles at any position.
⚠ Do not forget that this code will run in the browser alongside your application. Since not all browsers support latest ECMA features like
let
,const
,arrow function expression
and etc we recommend you to use only ECMA 5 features and syntax.
⚠ The
insert
function is serialized to string and passed to the plugin. This means that it won't have access to the scope of the webpack configuration module.
webpack.config.js
new MiniCssExtractPlugin({
insert: function (linkTag) {
var reference = document.querySelector("#some-element");
if (reference) {
reference.parentNode.insertBefore(linkTag, reference);
}
},
});
A new <link>
element will be inserted before the element with id some-element
.
attributes
Type:
type attributes = Record<string, string>};
Default: {}
[!WARNING]
Only for non-initial (async) chunks.
If defined, the mini-css-extract-plugin
will attach given attributes with their values on <link>
element.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
attributes: {
id: "target",
"data-target": "example",
},
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
[!NOTE]
It's only applied to dynamically loaded css chunks, if you want to modify link attributes inside html file, please using html-webpack-plugin
linkType
Type:
type linkType = string | boolean;
Default: text/css
This option allows loading asynchronous chunks with a custom link type, such as <link type="text/css" ...>
.
string
Possible values: text/css
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
linkType: "text/css",
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
boolean
false
disables the link type
attribute
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
linkType: false,
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
runtime
Type:
type runtime = boolean;
Default: true
Allows to enable/disable the runtime generation. CSS will be still extracted and can be used for a custom loading methods. For example, you can use assets-webpack-plugin to retrieve them then use your own runtime code to download assets when needed.
false
to skip.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
runtime: false,
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
experimentalUseImportModule
Type:
type experimentalUseImportModule = boolean;
Default: undefined
Enabled by default if not explicitly enabled (i.e. true
and false
allow you to explicitly control this option) and new API is available (at least webpack 5.52.0
is required).
Boolean values are available since version 5.33.2
, but you need to enable experiments.executeModule
(not required from webpack 5.52.0
).
Use a new webpack API to execute modules instead of child compilers. This improves performance and memory usage a lot.
When combined with experiments.layers
, this adds a layer
option to the loader options to specify the layer of the css execution.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// You don't need this for `>= 5.52.0` due to the fact that this is enabled by default
// Required only for `>= 5.33.2 & <= 5.52.0`
// Not available/unsafe for `<= 5.33.2`
experimentalUseImportModule: true,
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
publicPath
Type:
type publicPath =
| string
| ((resourcePath: string, rootContext: string) => string);
Default: the publicPath
in webpackOptions.output
Specifies a custom public path for the external resources like images, files, etc inside CSS
.
Works like output.publicPath
string
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "[name].css",
chunkFilename: "[id].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "/public/path/to/",
},
},
"css-loader",
],
},
],
},
};
function
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "[name].css",
chunkFilename: "[id].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: (resourcePath, context) => {
return path.relative(path.dirname(resourcePath), context) + "/";
},
},
},
"css-loader",
],
},
],
},
};
emit
Type:
type emit = boolean;
Default: true
If true, emits a file (writes a file to the filesystem). If false, the plugin will extract the CSS but will not emit the file. It is often useful to disable this option for server-side packages.
esModule
Type:
type esModule = boolean;
Default: true
By default, mini-css-extract-plugin
generates JS modules that use the ES modules syntax.
There are some cases in which using ES modules is beneficial, like in the case of module concatenation and tree shaking.
You can enable a CommonJS syntax using:
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
esModule: false,
},
},
"css-loader",
],
},
],
},
};
defaultExport
Type:
type defaultExport = boolean;
Default: false
[!NOTE]
This option will work only when you set
namedExport
totrue
incss-loader
By default, mini-css-extract-plugin
generates JS modules based on the esModule
and namedExport
options in css-loader
.
Using the esModule
and namedExport
options will allow you to better optimize your code.
If you set esModule: true
and namedExport: true
for css-loader
mini-css-extract-plugin
will generate only a named export.
Our official recommendation is to use only named export for better future compatibility.
But for some applications, it is not easy to quickly rewrite the code from the default export to a named export.
In case you need both default and named exports, you can enable this option:
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
defaultExport: true,
},
},
{
loader: "css-loader",
options: {
esModule: true,
modules: {
namedExport: true,
},
},
},
],
},
],
},
};
For production
builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on.
This can be achieved by using the mini-css-extract-plugin
, because it creates separate css files.
For development
mode (including webpack-dev-server
) you can use style-loader, because it injects CSS into the DOM using multiple and works faster.
Do not use
style-loader
andmini-css-extract-plugin
together.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";
module.exports = {
module: {
rules: [
{
// If you enable `experiments.css` or `experiments.futureDefaults`, please uncomment line below
// type: "javascript/auto",
test: /\.(sa|sc|c)ss$/,
use: [
devMode ? "style-loader" : MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader",
],
},
],
},
plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// all options are optional
filename: "[name].css",
chunkFilename: "[id].css",
ignoreOrder: false, // Enable to remove warnings about conflicting order
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// you can specify a publicPath here
// by default it uses publicPath in webpackOptions.output
publicPath: "../",
},
},
"css-loader",
],
},
],
},
};
⚠ Names of locals are converted to
camelCase
.
⚠ It is not allowed to use JavaScript reserved words in css class names.
⚠ Options
esModule
andmodules.namedExport
incss-loader
should be enabled.
styles.css
.foo-baz {
color: red;
}
.bar {
color: blue;
}
index.js
import { fooBaz, bar } from "./styles.css";
console.log(fooBaz, bar);
You can enable a ES module named export using:
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: "css-loader",
options: {
esModule: true,
modules: {
namedExport: true,
localIdentName: "foo__[name]__[local]",
},
},
},
],
},
],
},
};
publicPath
option as functionwebpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "[name].css",
chunkFilename: "[id].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: (resourcePath, context) => {
// publicPath is the relative path of the resource to the context
// e.g. for ./css/admin/main.css the publicPath will be ../../
// while for ./css/main.css the publicPath will be ../
return path.relative(path.dirname(resourcePath), context) + "/";
},
},
},
"css-loader",
],
},
],
},
};
This plugin should not be used with style-loader
in the loaders chain.
Here is an example to have both HMR in development
and your styles extracted in a file for production
builds.
(Loaders options left out for clarity, adapt accordingly to your needs.)
You should not use HotModuleReplacementPlugin
plugin if you are using a webpack-dev-server
.
webpack-dev-server
enables / disables HMR using hot
option.
webpack.config.js
const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";
const plugins = [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: devMode ? "[name].css" : "[name].[contenthash].css",
chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
}),
];
if (devMode) {
// only enable hot in development
plugins.push(new webpack.HotModuleReplacementPlugin());
}
module.exports = {
plugins,
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader",
],
},
],
},
};
[!NOTE]
HMR is automatically supported in webpack 5. No need to configure it. Skip the following:
The mini-css-extract-plugin
supports hot reloading of actual css files in development.
Some options are provided to enable HMR of both standard stylesheets and locally scoped CSS or CSS modules.
Below is an example configuration of mini-css for HMR use with CSS modules.
You should not use HotModuleReplacementPlugin
plugin if you are using a webpack-dev-server
.
webpack-dev-server
enables / disables HMR using hot
option.
webpack.config.js
const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const plugins = [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: devMode ? "[name].css" : "[name].[contenthash].css",
chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
}),
];
if (devMode) {
// only enable hot in development
plugins.push(new webpack.HotModuleReplacementPlugin());
}
module.exports = {
plugins,
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {},
},
"css-loader",
],
},
],
},
};
To minify the output, use a plugin like css-minimizer-webpack-plugin.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
optimization: {
minimizer: [
// For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
// `...`,
new CssMinimizerPlugin(),
],
},
};
This will enable CSS optimization only in production mode. If you want to run it also in development set the optimization.minimize
option to true.
The runtime code detects already added CSS via <link>
or <style>
tag.
This can be useful when injecting CSS on server-side for Server-Side-Rendering.
The href
of the <link>
tag has to match the URL that will be used for loading the CSS chunk.
The data-href
attribute can be used for <link>
and <style>
too.
When inlining CSS data-href
must be used.
The CSS can be extracted in one CSS file using optimization.splitChunks.cacheGroups
.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: "styles",
type: "css/mini-extract",
chunks: "all",
enforce: true,
},
},
},
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
Note that type
should be used instead of test
in Webpack 5, or else an extra .js
file can be generated besides the .css
file. This is because test
doesn't know which modules should be dropped (in this case, it won't detect that .js
should be dropped).
You may also extract the CSS based on the webpack entry name. This is especially useful if you import routes dynamically but want to keep your CSS bundled according to entry. This also prevents the CSS duplication issue one had with the ExtractTextPlugin.
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
foo: path.resolve(__dirname, "src/foo"),
bar: path.resolve(__dirname, "src/bar"),
},
optimization: {
splitChunks: {
cacheGroups: {
fooStyles: {
type: "css/mini-extract",
name: "styles_foo",
chunks: (chunk) => {
return chunk.name === "foo";
},
enforce: true,
},
barStyles: {
type: "css/mini-extract",
name: "styles_bar",
chunks: (chunk) => {
return chunk.name === "bar";
},
enforce: true,
},
},
},
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
With the filename
option you can use chunk data to customize the filename.
This is particularly useful when dealing with multiple entry points and wanting to get more control out of the filename for a given entry point/chunk.
In the example below, we'll use filename
to output the generated css into a different directory.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: ({ chunk }) => `${chunk.name.replace("/js/", "/css/")}.css`,
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
For long term caching use filename: "[contenthash].css"
. Optionally add [name]
.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
chunkFilename: "[id].[contenthash].css",
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
For projects where css ordering has been mitigated through consistent use of scoping or naming conventions, such as CSS Modules, the css order warnings can be disabled by setting the ignoreOrder flag to true for the plugin.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
ignoreOrder: true,
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/index.js",
module: {
rules: [
{
test: /\.s[ac]ss$/i,
oneOf: [
{
resourceQuery: "?dark",
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "sass-loader",
options: {
additionalData: `@use 'dark-theme/vars' as vars;`,
},
},
],
},
{
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "sass-loader",
options: {
additionalData: `@use 'light-theme/vars' as vars;`,
},
},
],
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
attributes: {
id: "theme",
},
}),
],
};
src/index.js
import "./style.scss";
let theme = "light";
const themes = {};
themes[theme] = document.querySelector("#theme");
async function loadTheme(newTheme) {
// eslint-disable-next-line no-console
console.log(`CHANGE THEME - ${newTheme}`);
const themeElement = document.querySelector("#theme");
if (themeElement) {
themeElement.remove();
}
if (themes[newTheme]) {
// eslint-disable-next-line no-console
console.log(`THEME ALREADY LOADED - ${newTheme}`);
document.head.appendChild(themes[newTheme]);
return;
}
if (newTheme === "dark") {
// eslint-disable-next-line no-console
console.log(`LOADING THEME - ${newTheme}`);
import(/* webpackChunkName: "dark" */ "./style.scss?dark").then(() => {
themes[newTheme] = document.querySelector("#theme");
// eslint-disable-next-line no-console
console.log(`LOADED - ${newTheme}`);
});
}
}
document.onclick = () => {
if (theme === "light") {
theme = "dark";
} else {
theme = "light";
}
loadTheme(theme);
};
src/dark-theme/_vars.scss
$background: black;
src/light-theme/_vars.scss
$background: white;
src/styles.scss
body {
background-color: vars.$background;
}
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Document</title>
<link id="theme" rel="stylesheet" type="text/css" href="./main.css" />
</head>
<body>
<script src="./main.js"></script>
</body>
</html>
If you'd like to extract the media queries from the extracted CSS (so mobile users don't need to load desktop or tablet specific CSS anymore) you should use one of the following plugins:
The mini-css-extract-plugin provides hooks to extend it to your needs.
SyncWaterfallHook
Called before inject the insert code for link tag. Should return a string
MiniCssExtractPlugin.getCompilationHooks(compilation).beforeTagInsert.tap(
"changeHref",
(source, varNames) =>
Template.asString([
source,
`${varNames.tag}.setAttribute("href", "/plugins/mini-css-extract-plugin/));`,
])
);
Please take a moment to read our contributing guidelines if you haven't yet done so.
과거에 번들링을 할 때 webpack의 절충점 중 하나는 번들의 각 모듈이 개별 함수 클로저에 의해 래핑된다는 점이었습니다. 이러한 래퍼 함수는 브라우저에서 자바스크립트의 실행을 느리게 만들었습니다. 이와 달리, Closure Comiler와 RollupJS와 같은 도구는 모든 모듈을 하나의 클로저로 호이스팅 하거나 연결하여 코드가 브라우저에서 더 빠른 실행 시간을 갖게 했습니다.
이 플러그인은 위의 내용과 같은 연결 동작이 webpack에서 가능하게 해줍니다. 기본적으로 이 플러그인은 production mode
에서는 이미 가능하고 나머지에서는 아직 가능하지 않습니다. 만약 생산 mode
최적화를 무효로 해야 하는 경우, optimization.concatenateModules
옵션을 false
로 설정하세요. 다른 모드에서 연결 동작을 가능하게 하고 싶을 경우, ModuleConcatenationPlugin
을 수동으로 설정하거나 optimization.concatenateModules
옵션을 사용하세요.
new webpack.optimize.ModuleConcatenationPlugin();
이 연결 동작은 “범위 호이스팅” 이라고 불립니다.
범위 호이스팅은 특별히 ECMAScript Module 문법에서 사용 가능하도록 만들어진 형태입니다. 이로 인해 webpack은 현재 사용 중인 모듈의 종류와 다른 여러 조건에 따라 평범한 번들링으로 퇴화할 수도 있습니다.
글에서 설명하듯이 webpack은 부분적인 범위 호이스팅을 시도합니다. 이는 모듈을 하나의 범위로 합치지만 모든 경우에 합치지는 못합니다. 만약 webapck이 모듈을 합칠 수 없다면 두 가지 대안은 Prevent와 Root 입니다. Prevent는 모듈이 반드시 그 자신의 범위 안에 있어야 한다는 것을 의미합니다. Root는 새로운 모듈 그룹이 생성될 것이라는 의미입니다. 다음의 조건이 결과를 결정합니다.
Condition | Outcome |
---|---|
Non ES6 Module | Prevent |
Non Import로 가져옴 | Root |
다른 청크에서 가져옴 | Root |
다수의 다른 모듈 그룹에서 가져옴 | Root |
import() 로 가져옴 | Root |
ProvidePlugin 의 영향을 받거나 module 사용 | Prevent |
HMR 허용 | Root |
eval() 사용 | Prevent |
다수의 청크 | Prevent |
"cjs-module"로부터 * 내보내기 | Prevent |
아래의 자바스크립트 의사코드는 이 알고리즘을 설명합니다.
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;
}
webpack CLI를 사용할 경우 --stats-optimization-bailout
플래그는 bailout 원인을 보여줍니다. webpack config를 사용할 경우 stats
객체에 다음을 추가하세요.
module.exports = {
//...
stats: {
// Display bailout reasons
optimizationBailout: true,
},
};
Webpack에는 많은 플러그인 인터페이스가 있습니다. Webpack 자체에 있는 대부분의 기능은 플러그인 인터페이스를 사용합니다. 이런점이 webpack을 유연하게 만듭니다.
이름 | 설명 |
---|---|
BannerPlugin | 생성된 청크의 상단에 배너 추가 |
ChunksWebpackPlugin | 번들을 제공하기 위해 엔트리 포인트 및 청크 관계가 포함된 HTML 파일 생성 |
CommonsChunkPlugin | 청크 간에 공유되는 공통 모듈 추출 |
CompressionWebpackPlugin | Content-Encoding으로 제공할 압축된 버전의 애셋 준비 |
ContextReplacementPlugin | require 표현식의 유추된 컨텍스트 재정의 |
CopyWebpackPlugin | 개별 파일 또는 전체 디렉터리를 빌드 디렉터리에 복사 |
DefinePlugin | 컴파일 타임에 전역 변수 선언 |
DllPlugin | 빌드 시간을 단축시키기 위해 번들 분할 |
EnvironmentPlugin | process.env 키에서 DefinePlugin 을 사용하는 약어 |
EslintWebpackPlugin | webpack을 위한 ESLint 플러그인 |
HotModuleReplacementPlugin | Hot Module Replacement (HMR) 활성화 |
HtmlWebpackPlugin | 번들을 제공하기 위한 HTML 파일을 쉽게 생성 |
IgnorePlugin | 번들에서 특정 모듈 제외 |
LimitChunkCountPlugin | 청킹을 더 잘 제어하기 위한 청킹의 최소/최대 제한 설정 |
MinChunkSizePlugin | 청크 크기를 지정한 제한 이상으로 유지 |
MiniCssExtractPlugin | CSS파일을 필요로하는 JS파일만 CSS파일을 생성 |
NoEmitOnErrorsPlugin | 컴파일 오류가 있는 경우 방출 단계를 건너뜀 |
NormalModuleReplacementPlugin | 정규식과 일치하는 리소스 교체 |
NpmInstallWebpackPlugin | 개발단계에서 누락된 디펜던시 자동 설치 |
ProgressPlugin | 컴파일 진행률 보고 |
ProvidePlugin | import 또는 require 사용없이 모듈 사용 |
SourceMapDevToolPlugin | 소스맵을 세밀하게 제어 |
EvalSourceMapDevToolPlugin | eval 소스맵을 세밀하게 제어 |
SvgChunkWebpackPlugin | 엔트리 포인트의 의존성을 기반으로 SVGO에 의해 최적화된 SVG 스프라이트 생성 |
TerserPlugin | Terser를 사용하여 JS 압축 |
더 많은 써드 파티 플러그인을 찾고 싶다면, awesome-webpack을 참고하세요.
ModuleFederationPlugin
을 사용하면 런타임에 다른 독립 빌드와 함께 모듈을 제공하거나 사용할 수 있습니다.
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
// 여러 옵션을 타입스크립트로 작성합니다.
runtime: string | false,
}),
],
};
특정한 이름으로 새로운 런타임 청크를 만듭니다.
webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
runtime: 'my-runtime-name',
}),
],
};
설정의 '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 /
구문을 사용하면 패키지의 모든 파일에 액세스할 수 있습니다. 그러나 특히 개발
모드에서는 성능에 영향을 미치므로 필요한 경우에만 사용해야 합니다.
공유 라이브러리의 버전을 지정하는 세 가지 방법이 있습니다.
이 구문을 사용하면 패키지 이름만 있는 라이브러리를 공유할 수 있습니다. 이 접근 방식은 프로토타이핑에 적합하지만 react
및 react-dom
과 같은 라이브러리에 추가 요구 사항이 필요하기 때문에 대규모 프로덕션 환경으로 확장할 수 없습니다.
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
// lodash를 공유 모듈로 추가합니다.
// package.json으로부터 버전을 추론합니다.
// 필수 버전을 확인하지 않습니다.
// 그래서 항상 발견된 더 높은 버전을 사용합니다.
shared: ['lodash'],
}),
],
};
이 구문을 사용하면 패키지 이름을 키로 정의하고 버전(semver)을 값으로 정의할 수 있는 각 공유 라이브러리를 보다 세부적으로 제어할 수 있습니다.
module.exports = {
plugins: [
new ModuleFederationPlugin({
shared: {
// lodash를 공유 모듈로 추가합니다.
// package.json 으로부터 버전을 추론합니다.
// 4.17 이상 5 미만의 버전 중 최상위 버전을 사용하게 됩니다.
lodash: '^4.17.0',
},
}),
],
};
이 구문을 사용하면 각 공유 패키지에 힌트를 추가로 제공할 수 있습니다. 패키지의 이름을 키로, 공유 동작을 수정하기 위한 힌트를 포함한 객체를 값으로 정의하여 제공할 수 있습니다.
const deps = require('./package.json').dependencies;
module.exports = {
plugins: [
new ModuleFederationPlugin({
shared: {
// react를 공유 모듈로 추가합니다.
react: {
requiredVersion: deps.react,
singleton: true,
},
},
}),
],
};
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
파일에 있는 버전을 사용합니다.
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
을 사용하면 오류가 있을 때 애셋 방출을 피할 수 있습니다. 기본적으로 활성화되어 있으며, optimization.emitOnErrors
를 사용하여 비활성화 할 수 있습니다.
webpack.config.js
module.exports = {
plugins: [new webpack.NoEmitOnErrorsPlugin()],
};
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/,
를 대신 사용해야 합니다.
개발 환경용으로 빌드할 때 특정 모듈을 교체합니다.
some/path/config.development.module.js
설정 파일과 some/path/config.production.module.js
에 프로덕션용 특수 버전이 있다면
프로덕션용으로 빌드할 때 다음 플러그인을 추가합니다.
new webpack.NormalModuleReplacementPlugin(
/some\/path\/config\.development\.js/,
'./config.production.js'
);
지정된 환경에 따른 조건부 빌드에 관한 내용입니다.
다른 빌드 대상에 대한 특정 값이 포함된 설정을 원한다고 가정해 보겠습니다.
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'
일반 모듈의 요청을 프리페치하면 첫 번째에 import
또는 require
가 발생하기 전에 요청을 확인하고 빌드합니다. 플러그인을 사용함으로써 성능을 높일 수 있습니다. 영리한 프리페칭 지점을 결정하기 위해, 먼저 빌드를 프로파일링 하세요.
new webpack.PrefetchPlugin([context], request);
context
: 디렉터리에 대한 절대경로request
: 일반 모듈에 대한 요청 문자열플러그인 실행 시간이 포함된 Chrome 프로필 파일을 생성합니다. 기본적으로 events.json
파일을 출력합니다. outputPath
옵션을 사용하여 커스텀 파일 경로를 제공할 수 있습니다.
참고: ProfilingPlugin은 절대 경로만 사용합니다.
outputPath
: 커스텀 출력 파일(json)의 절대 경로new webpack.debug.ProfilingPlugin();
outputPath
new webpack.debug.ProfilingPlugin({
outputPath: path.join(__dirname, 'profiling/profileEvents.json'),
});
프로필 파일을 보기 위해서는 다음과 같은 과정을 따릅니다.
ProfilingPlugin
과 함께 webpack을 실행합니다.Performance
탭(이전 명칭 Timeline
)으로 이동합니다.events.json
)을 profiler로 끌어다 놓습니다.위와 같은 과정을 거치면 plugin당 timeline 통계와 호출들이 표시될 것입니다!
ProgressPlugin
은 컴파일 도중에 진행 상황을 보고받을 방법을 자신이 원하는대로 정하는 방법을 제공합니다.
ProgressPlugin
의 인스턴스를 만들고, 허용되는 여러 매개변수 중 하나를 제공하며, 기본 핸들러를 사용자 지정하는 데 사용할 수 있는 정적 메서드 createDefaultHandler
도 있습니다.
function
훅이 진행 상황을 보고할 때 호출될 handler 함수를 제공합니다. 함수 handler
의 실행 인자:
percentage
: 컴파일의 성공 확률을 나타내는 0과 1 사이의 숫자message
: 현재 실행중인 훅에 대한 짧은 설명...args
: 현재 실행 상황을 묘사하는 0개 이상의 추가적인 문자열const handler = (percentage, message, ...args) => {
// 예를 들어, 각 진행 메세지를 콘솔에 직접 출력
console.info(percentage, message, ...args);
};
new webpack.ProgressPlugin(handler);
object
ProgressPlugin
에 object
를 제공할 때, 다음의 속성이 지원됩니다
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,
});
ProgressPlugin
의 기본 핸들러가 요구 사항을 충족하지 않는 경우 정적 ProgressPlugin.createDefaultHandler
메서드를 사용하여 사용자 지정할 수 있습니다.
static createDefaultHandler: (
profile: undefined | null | boolean,
logger: WebpackLogger
) => (percentage: number, msg: string, ...args: string[]) => void;
기본적으로 진행률은 빌드된 모듈 수와 총 모듈 수를 기반으로 계산됩니다: built / total
총 모듈 수는 사전에는 알 수 없고 빌드를 거치면서 변합니다. 이는 부정확한 진행률을 야기할 수 있습니다.
이러한 문제를 해결하기 위해 ProgressPlugin
은 마지막으로 알려진 총 모듈 수를 캐시하여 이 값을 다음 빌드 때 재사용합니다. 첫 번째 빌드는 데이터 값을 메모리에 캐시하지만 그 다음 빌드들은 이 값을 사용하고 업데이트합니다.
다중 구성된 엔트리 포인트가 있는 프로젝트들을 위한 설정에는
percentBy: 'entries'
를 사용할 것을 추천합니다. 엔트리 포인트의 개수를 미리 알 수 있기 때문에 확률 계산은 더욱 정확해질 것입니다.
다음 훅은 ProgressPlugin
에 진행 정보를 보고합니다.
Compiler
Compilation
모듈을 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를 가져오려면 모듈의 기본 프로퍼티를 지정해야 합니다.
jquery
를 자동으로 로드하려면 해당 노드 모듈에 노출되는 두 변수를 모두 가리킬 수 있습니다.
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
});
소스 코드 중 어느 것이라도 동일합니다.
// 모듈에서
$('#item'); // <= 동작합니다.
jQuery('#item'); // <= 이 또한 동작합니다.
// $는 모듈 "jquery" exports로 자동 설정되었습니다.
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',
});
new webpack.ProvidePlugin({
_map: ['lodash', 'map'],
});
new webpack.ProvidePlugin({
Vue: ['vue/dist/vue.esm.js', 'default'],
});
이 플러그인을 사용하면 소스맵 생성을 더욱더 세밀하게 제어 할 수 있습니다. 이 플러그인은 devtool
의 설정 옵션을 통해 자동으로 활성화됩니다.
new webpack.SourceMapDevToolPlugin(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]
에 나타나지 않도록 상위 디렉터리에 소스맵을 저장하려는 경우에 유용합니다.
다음은 이 플러그인의 몇 가지 일반적인 사용 사례입니다.
다음 코드를 사용하여 설정 옵션 devtool: inline-source-map
을 커스텀 플러그인 설정으로 동등하게 바꿀 수 있습니다.
module.exports = {
// ...
devtool: false,
plugins: [new webpack.SourceMapDevToolPlugin({})],
};
다음 코드는 vendor.js
번들 내 모듈의 소스맵을 제외합니다.
new webpack.SourceMapDevToolPlugin({
filename: '[file].map[query]',
exclude: ['vendor.js'],
});
소스맵의 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
원래 청크(및 그 안에 가져온 모듈)는 webpack 내부 그래프에서 부모-자식 관계로 연결되었습니다. CommonsChunkPlugin
은 중복되는 의존성을 피하고자 사용되었지만, 추가 최적화는 불가능했습니다.
webpack v4부터 optimization.splitChunks
를 위해 CommonsChunkPlugin
은 제거되었습니다.
즉시 사용 가능한 SplitChunksPlugin
은 대부분의 사용자에게 잘 작동합니다.
초기 청크를 변경하면 HTML 파일이 프로젝트를 실행하기 위해 포함해야 하는 스크립트 태그에 영향을 미치기 때문에 기본적으로 on-demand 청크에만 영향을 미칩니다.
Webpack은 다음 조건에 따라 자동으로 청크를 분할합니다.
node_modules
폴더에 있는 경우마지막 두 가지 조건을 충족하려고 할 때 더 큰 청크가 선호됩니다.
Webpack은 이 기능에 대한 더 많은 제어를 원하는 개발자를 위해 옵션 세트를 제공합니다.
이 설정 객체는 SplitChunksPlugin
의 기본 동작을 나타냅니다.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',
minSize: 20000,
minRemainingSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
string = '~'
기본적으로 webpack은 출처와 청크 이름을 사용하여 이름을 생성합니다(예: vendors~main.js
). 이 옵션을 사용하면 생성된 이름에 사용할 구분 기호를 지정할 수 있습니다.
string = 'async'
function (chunk)
RegExp
이것은 최적화를 위해 선택될 청크를 나타냅니다. 문자열이 제공될 때 유효한 값은 all
, async
및 initial
입니다. 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/,
},
},
};
number = 30
on-demand 로드 시의 최대 병렬 요청 수입니다.
number = 30
엔트리 포인트의 최대 병렬 요청 수입니다.
[string] = ['javascript', 'unknown']
크기에 숫자를 사용할 때 적용되는 크기 유형을 설정합니다.
number = 1
모듈이 분할 전에 청크 간에 공유되어야 하는 최소 개수입니다.
boolean
maxSize로 분할된 부분의 이름을 만들 때 경로 정보가 노출되지 않도록 합니다.
number = 20000
{ [index: string]: number }
생성할 청크의 최소 byte 크기입니다.
number
{ [index: string]: number }
청크를 생성하는 데 필요한 기본 청크(번들)의 바이트 단위의 줄어들 최소 크기입니다. 즉, 청크로 분할해도 기본 청크(번들)의 크기가 주어진 바이트만큼 줄어들지 않으면 splitChunks.minSize
값을 충족하더라도 분할되지 않습니다.
splitChunks.cacheGroups.{cacheGroup}.enforceSizeThreshold
number = 50000
분할이 적용되고 기타 제한(minRemainingSize, maxAsyncRequests, maxInitialRequests)이 무시되는 임계 크기 값입니다.
splitChunks.cacheGroups.{cacheGroup}.minRemainingSize
number = 0
splitChunks.minRemainingSize
옵션은 분할 후 남아있는 청크의 최소 크기가 제한을 초과하도록 하여 크기가 0인 모듈을 방지하기 위해 webpack 5에 도입되었습니다. 'development' 모드에서 기본값은 0
입니다. 다른 경우 splitChunks.minRemainingSize
는 기본적으로 splitChunks.minSize
값으로 설정되므로 심층 제어가 필요한 드문 경우를 제외하고는 수동으로 지정할 필요가 없습니다.
splitChunks.cacheGroups.{cacheGroup}.layer
RegExp
string
function
모듈 계층별로 캐시 그룹에 모듈을 할당합니다.
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 및 장기 캐싱과 함께 사용하기 위한 것입니다. 더 나은 캐싱을 위해 요청수가 증가합니다. 빠른 재구축을 위해 파일 크기를 줄이는 데도 사용할 수 있습니다.
number
maxSize
와 마찬가지로 maxAsyncSize
는 전역적으로(splitChunks.maxAsyncSize
) 캐시 그룹(splitChunks.cacheGroups.{cacheGroup}.maxAsyncSize
) 또는 대체 캐시 그룹(splitChunks.fallbackCacheGroup.maxAsyncSize
)에 적용될 수 있습니다.
maxAsyncSize
와 maxSize
의 차이점은 maxAsyncSize
가 on-demand 로딩 청크에만 영향을 미친다는 점입니다.
number
maxSize
와 마찬가지로 maxInitialSize
는 전역적으로(splitChunks.maxInitialSize
) 캐시 그룹(splitChunks.cacheGroups.{cacheGroup}.maxInitialSize
) 또는 대체 캐시 그룹(splitChunks.fallbackCacheGroup.maxInitialSize
)에 적용될 수 있습니다.
maxInitialSize
와 maxSize
의 차이점은 maxInitialSize
가 초기 로딩 청크 에만 영향을 미친다는 것입니다.
boolean = false
function (module, chunks, cacheGroupKey) => string
string
또한 splitChunks.cacheGroups.{cacheGroup}.name
와 같이 각 캐시 그룹에 대해서도 사용 가능합니다.
이는 분할 청크의 이름입니다. false
를 제공하면 청크의 이름이 동일하게 유지되므로 불필요하게 이름이 변경되지 않습니다. 프로덕션 빌드에 권장되는 값입니다.
문자열이나 함수를 제공하면 이름을 커스텀 할 수 있습니다. 항상 같은 문자열을 반환하는 문자열이나 함수를 지정하면 모든 공통 모듈과 vendor가 단일 청크로 병합됩니다. 이로 인해 초기 다운로드가 더 커지고 페이지 로드가 느려질 수 있습니다.
함수를 명시한 경우 청크의 이름을 선택하는 데 특히 유용한 chunk.name
속성(여기서 chunk
는 chunks
배열의 요소)을 찾을 수 있습니다.
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.cacheGroups{cacheGroup}.usedExports
boolean = true
모듈이 export 할 파일의 이름을 수정(mangle)하고 사용하지 않는 export를 생략하고 보다 효율적인 코드를 생성하기 위해 어떤 export를 사용하는지 알아봅니다.
true
인 경우 각 런타임에 대해 사용된 export를 분석하고, "global"
인 경우 결합한 모든 런타임에 대해 전역적으로 export를 분석합니다.
캐시 그룹은 splitChunks.*
의 모든 옵션을 상속 및(또는) 재정의할 수 있습니다. 그러나 test
, priority
및 reuseExistingChunk
는 캐시 그룹 수준에서만 구성할 수 있습니다. 기본 캐시 그룹을 비활성화하려면 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.{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';
},
},
},
},
},
};
module
및 chunks
객체에서 어떤 정보를 사용할 수 있는지 확인하려면 콜백에 debugger;
문을 넣으면 됩니다. 그런 다음 디버그 모드에서 webpack 빌드를 실행하여 Chromium DevTools의 파라미터를 검사합니다.
아래는 {cacheGroup}.test
에 RegExp
를 제공한 경우입니다.
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.maxAsyncRequests
및 splitChunks.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',
},
},
},
},
};
// index.js
import('./a'); // 동적 import
// a.js
import 'react';
//...
결과: react
를 포함하는 별도의 청크가 생성됩니다. import 호출에서 이 청크는 ./a
를 포함하는 원래 청크와 병렬로 로드됩니다.
이유:
node_modules
의 모듈을 포함합니다react
가 30kb보다 큽니다이 이유는 무엇일까요? react
는 애플리케이션 코드만큼 자주 변경되지 않을 것입니다. 별도의 청크로 이동하면 이 청크를 앱 코드와 별도로 캐시할 수 있습니다(청크 해시, 레코드, Cache-Control 또는 장기 캐시 접근 방식을 사용한다고 가정합니다).
// 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 호출에서 이 청크는 원래 청크와 병렬로 로드됩니다.
이유:
helpers
는 30kb보다 큽니다helpers
의 내용을 각 청크에 넣으면 코드가 두 번 다운로드됩니다. 별도의 청크를 사용하면 한 번만 발생합니다. 우리는 추가 요청 비용을 지불하며 이는 절충안으로 간주할 수 있습니다. 그렇기 때문에 최소 크기는 30kb입니다.
엔트리 포인트 간에 공유되는 모든 코드를 포함하는 commons
청크를 만듭니다.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: 'commons',
chunks: 'initial',
minChunks: 2,
},
},
},
},
};
전체 애플리케이션에서 node_modules
의 모든 코드를 포함하는 vendors
청크를 만듭니다.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
};
RegExp
와 일치하는 특정 node_modules
패키지를 포함하는 custom vendor
청크를 만듭니다.
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: 'vendor',
chunks: 'all',
},
},
},
},
};
This version of stylelint-webpack-plugin only works with webpack 5. For the webpack 4, see the 2.x branch.
This plugin uses stylelint
that helps you avoid errors and enforce conventions in your styles.
To begin, you'll need to install stylelint-webpack-plugin
:
npm install stylelint-webpack-plugin --save-dev
or
yarn add -D stylelint-webpack-plugin
or
pnpm add -D stylelint-webpack-plugin
[!NOTE]
You also need to install
stylelint >= 13
from npm, if you haven't already:
npm install stylelint --save-dev
or
yarn add -D stylelint
or
pnpm add -D stylelint
[!NOTE]
If you are using Stylelint 13 rather than 14+, you might also need to install
@types/stylelint
as a dev dependency if getting stylelint related type errors.
Then add the plugin to your webpack config. For example:
const StylelintPlugin = require('stylelint-webpack-plugin');
module.exports = {
// ...
plugins: [new StylelintPlugin(options)],
// ...
};
See stylelint's options for the complete list of options available. These options are passed through to the stylelint
directly.
cache
type cache = boolean;
true
The cache is enabled by default to decrease execution time.
cacheLocation
type cacheLocation = string;
node_modules/.cache/stylelint-webpack-plugin/.stylelintcache
Specify the path to the cache location. Can be a file or a directory.
configFile
type context = string;
undefined
Specify the config file location to be used by stylelint
.
Note:
By default this is handled by
stylelint
.
context
type context = string;
compiler.context
A string indicating the root of your files.
exclude
type exclude = string | Array<string>;
['node_modules', compiler.options.output.path]
Specify the files and/or directories to exclude. Must be relative to options.context
.
extensions
type extensions = string | Array<string>;
['css', 'scss', 'sass']
Specify extensions that should be checked.
files
type files = string | Array<string>;
null
Specify directories, files, or globs. Must be relative to options.context
. Directories are traversed recursively looking for files matching options.extensions
. File and glob patterns ignore options.extensions
.
fix
type fix = boolean;
false
If true
, stylelint
will fix as many errors as possible. The fixes are made to the actual source files. All unfixed errors will be reported. See Autofixing errors docs.
formatter
type formatter = string | (
results: Array<import('stylelint').LintResult>
) => string
'string'
Specify the formatter that you would like to use to format your results. See formatter option.
lintDirtyModulesOnly
type lintDirtyModulesOnly = boolean;
false
Lint only changed files, skip lint on start.
stylelintPath
type stylelintPath = string;
stylelint
Path to stylelint
instance that will be used for linting.
threads
type threads = boolean | number;
false
Set to true for an auto-selected pool size based on number of cpus. Set to a number greater than 1 to set an explicit pool size. Set to false, 1, or less to disable and only run in main process.
By default the plugin will auto adjust error reporting depending on stylelint errors/warnings counts.
You can still force this behavior by using emitError
or emitWarning
options:
emitError
type emitError = boolean;
true
The errors found will always be emitted, to disable set to false
.
emitWarning
type emitWarning = boolean;
true
The warnings found will always be emitted, to disable set to false
.
failOnError
type failOnError = boolean;
true
Will cause the module build to fail if there are any errors, to disable set to false
.
failOnWarning
type failOnWarning = boolean;
false
Will cause the module build to fail if there are any warnings, if set to true
.
quiet
type quiet = boolean;
false
Will process and report errors only and ignore warnings, if set to true
.
outputReport
type outputReport =
| boolean
| {
filePath?: string | undefined;
formatter?:
| (
| string
| ((results: Array<import('stylelint').LintResult>) => string)
)
| undefined;
};
false
Write the output of the errors to a file, for example a json
file for use for reporting.
The filePath
is relative to the webpack config: output.path
.
You can pass in a different formatter for the output file, if none is passed in the default/configured formatter will be used.
{
filePath: 'path/to/file';
formatter: 'json';
}
The svg-chunk-webpack-plugin
creates optimized SVG sprites, according to Webpack's entrypoints. Each sprite contains only the SVG dependencies listed on its entrypoints to improved code splitting, even on SVG files.
The plugin includes the popular SVGO package to generates clean and optimized SVG sprites.
Code splitting is the key to deliver files without any content that is unused by the pages. It already exists for CSS, Javascript and now for SVG files with this plugin.
On multiple page application, each pages must includes only its necessary dependencies. In other words, it must include only the SVG files imported by its entrypoint and all its dependencies.
With reusable components, SVGs are often duplicated on all the project. Now, you can create a global SVG library and every Javascript files can easily import any SVG from this library. Entrypoint dependencies are automatically updated, thanks to the Webpack compilation.
When you work with SVGs exported by design softwares, like Sketch or Illustrator, their source code is never optimized and often contains comments, CSS classes which can create conflicts between them. The plugin automatically cleans all SVGs before creating the sprite.
The plugin works without configuration with already the optimized settings. For advanced usage, see the section using configuration.
The plugin is available as a package with the name of svg-chunk-webpack-plugin
on npm and Github.
npm install svg-chunk-webpack-plugin --save-dev
yarn add svg-chunk-webpack-plugin --dev
Warning
svg-chunk-webpack-plugin@5
is ESM only.Note Minimum supported
Node.js
version is16.20.0
and Webpack>=5.10.3
.
The project includes a minimalist example in the ./example
directory. Run the npm run build:example
command to execute the Webpack example and see the plugin's implementation in action.
The plugin will generate one SVG sprite for each entrypoints. Sprites are built in the output path directory with all the other assets. Each sprite filename is composed with its entrypoint name (in the example below, that would be home.svg
).
First, let's add the loader and the plugin to the Webpack configuration.
Warning The loader and the plugin need to works together.
webpack.config.js
import SvgChunkWebpackPlugin from 'svg-chunk-webpack-plugin';
export default {
module: {
rules: [
{
test: /\.svg$/,
use: [
{
loader: SvgChunkWebpackPlugin.loader
}
]
}
]
},
plugins: [new SvgChunkWebpackPlugin()]
};
Note
For more flexibility and better performance, inline SVG files are better. Fewer HTTP requests, CSS properties to change the style, no flickering during the page load.
Then, include the sprite in the wanted pages (we use Twig in the following example).
home.html.twig
{{ include 'home.svg' }}
Finally, use the SVG with the <use>
tag, like the following example. Replace <svg_name>
by the SVG name (without the extension).
home.html.twig
<svg>
<use href="#<svg_name>"></use>
</svg>
The loader and the plugin accepts configuration to override the default behavior.
The loader configuration allow to personalize the SVGO configuration. SVGO optimization is executed during the loader process to optimize build performance.
configFile
Type:
type configFile = string | boolean;
Default: path.resolve(opts.root, 'svgo.config.js')
Tells the loader whether to load the custom SVGO configuration. Custom configuration can be disabled with configFile: false
.
webpack.config.js
export default {
module: {
rules: [
{
test: /\.svg$/,
loader: SvgChunkWebpackPlugin.loader,
options: {
configFile: './path/svgo.config.js'
}
}
]
}
};
SVGO have a default preset to optimize SVG files. See how to configure svgo for details.
svgo.config.js
export default {
multipass: true,
plugins: [
{
name: 'preset-default',
params: {
overrides: {
inlineStyles: {
onlyMatchedOnce: false
},
removeViewBox: false
}
}
},
{
name: 'convertStyleToAttrs'
}
]
};
The plugin configuration allow to personalize sprite settings.
filename
Type:
type filename = string;
Default: '[name].svg'
Tells the plugin whether to personalize the default sprite filename. The placeholder [name]
is automatically replaced by entrypoints names.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
filename: '[name].svg'
})
]
};
Note The
filename
parameter is compatible with Webpack caching placeholders, see the section caching.
svgstoreConfig
Type:
type svgstoreConfig = object;
Default: { cleanDefs: false, cleanSymbols: false, inline: true }
SVG sprites are built using the svgstore
package. Update the parameters according to your needs from the options list available on the svgstore documentation.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
svgstoreConfig: {
svgAttrs: {
'aria-hidden': true,
style: 'position: absolute; width: 0; height: 0; overflow: hidden;'
}
}
})
]
};
Note To avoid LinearGradient conflicts, avoid the
display: none
property which breaks SVG definitions.
generateSpritesManifest
Type:
type generateSpritesManifest = boolean;
Default: false
Tells the plugin whether to generate the sprites-manifest.json
. The JSON file contains the list of all SVG included by entrypoints.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
generateSpritesManifest: true
})
]
};
generateSpritesPreview
Type:
type generateSpritesPreview = boolean;
Default: false
Tells the plugin whether to generate the sprites-preview.html
. The HTML preview contains a display list of all SVG included by entrypoints with the SVG overviews and the names. See the sprites preview of the example.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
generateSpritesPreview: true
})
]
};
With webpack caching, several placeholders are available depending on your needs. With SVG inlined in the page, this option is not useful.
Note
The
[contenthash]
placeholder is the best option because it depends on the sprite content. Cache placeholders are expensive in build performance, use it only in production mode.
[contenthash]
The [contenthash]
placeholder will add a unique hash based on the content of the sprite. When the sprite's content changes, the hash will change as well.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
filename: '[name].[contenthash].svg'
})
]
};
[fullhash]
The [fullhash]
placeholder will add a unique hash generated for every build. When the compilation build is updated, the hash will change as well.
webpack.config.js
export default {
plugins: [
new SvgChunkWebpackPlugin({
filename: '[name].[fullhash].svg'
})
]
};
svg-chunk-webpack-plugin
is licensed under the MIT License.
Created with ♥ by @yoriiis.
This plugin uses terser to minify/minimize your JavaScript.
Webpack v5 comes with the latest terser-webpack-plugin
out of the box. If you are using Webpack v5 or above and wish to customize the options, you will still need to install terser-webpack-plugin
. Using Webpack v4, you have to install terser-webpack-plugin
v4.
To begin, you'll need to install terser-webpack-plugin
:
npm install terser-webpack-plugin --save-dev
or
yarn add -D terser-webpack-plugin
or
pnpm add -D terser-webpack-plugin
Then add the plugin to your webpack
config. For example:
webpack.config.js
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
},
};
And run webpack
via your preferred method.
Works only with source-map
, inline-source-map
, hidden-source-map
and nosources-source-map
values for the devtool
option.
Why?
eval
wraps modules in eval("string")
and the minimizer does not handle strings.cheap
has not column information and minimizer generate only a single line, which leave only a single mapping.Using supported devtool
values enable source map generation.
test
Type:
type test = string | RegExp | Array<string | RegExp>;
Default: /\.m?js(\?.*)?$/i
Test to match files against.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
test: /\.js(\?.*)?$/i,
}),
],
},
};
include
Type:
type include = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to include.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
include: /\/includes/,
}),
],
},
};
exclude
Type:
type exclude = string | RegExp | Array<string | RegExp>;
Default: undefined
Files to exclude.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
exclude: /\/excludes/,
}),
],
},
};
parallel
Type:
type parallel = boolean | number;
Default: true
Use multi-process parallel running to improve the build speed.
Default number of concurrent runs: os.cpus().length - 1
.
Note
Parallelization can speedup your build significantly and is therefore highly recommended.
Warning
If you use Circle CI or any other environment that doesn't provide real available count of CPUs then you need to setup explicitly number of CPUs to avoid
Error: Call retries were exceeded
(see #143, #202).
boolean
Enable/disable multi-process parallel running.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
}),
],
},
};
number
Enable multi-process parallel running and set number of concurrent runs.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: 4,
}),
],
},
};
minify
Type:
type minify = (
input: {
[file: string]: string;
},
sourceMap: import("@jridgewell/trace-mapping").SourceMapInput | undefined,
minifyOptions: {
module?: boolean | undefined;
ecma?: import("terser").ECMA | undefined;
},
extractComments:
| boolean
| "all"
| "some"
| RegExp
| ((
astNode: any,
comment: {
value: string;
type: "comment1" | "comment2" | "comment3" | "comment4";
pos: number;
line: number;
col: number;
}
) => boolean)
| {
condition?:
| boolean
| "all"
| "some"
| RegExp
| ((
astNode: any,
comment: {
value: string;
type: "comment1" | "comment2" | "comment3" | "comment4";
pos: number;
line: number;
col: number;
}
) => boolean)
| undefined;
filename?: string | ((fileData: any) => string) | undefined;
banner?:
| string
| boolean
| ((commentsFile: string) => string)
| undefined;
}
| undefined
) => Promise<{
code: string;
map?: import("@jridgewell/trace-mapping").SourceMapInput | undefined;
errors?: (string | Error)[] | undefined;
warnings?: (string | Error)[] | undefined;
extractedComments?: string[] | undefined;
}>;
Default: TerserPlugin.terserMinify
Allows you to override default minify function. By default plugin uses terser package. Useful for using and testing unpublished versions or forks.
Warning
Always use
require
insideminify
function whenparallel
option enabled.
webpack.config.js
// Can be async
const minify = (input, sourceMap, minimizerOptions, extractsComments) => {
// The `minimizerOptions` option contains option from the `terserOptions` option
// You can use `minimizerOptions.myCustomOption`
// Custom logic for extract comments
const { map, code } = require("uglify-module") // Or require('./path/to/uglify-module')
.minify(input, {
/* Your options for minification */
});
return { map, code, warnings: [], errors: [], extractedComments: [] };
};
// Used to regenerate `fullhash`/`chunkhash` between different implementation
// Example: you fix a bug in custom minimizer/custom function, but unfortunately webpack doesn't know about it, so you will get the same fullhash/chunkhash
// to avoid this you can provide version of your custom minimizer
// You don't need if you use only `contenthash`
minify.getMinimizerVersion = () => {
let packageJson;
try {
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
packageJson = require("uglify-module/package.json");
} catch (error) {
// Ignore
}
return packageJson && packageJson.version;
};
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
myCustomOption: true,
},
minify,
}),
],
},
};
terserOptions
Type:
type terserOptions = {
compress?: boolean | CompressOptions;
ecma?: ECMA;
enclose?: boolean | string;
ie8?: boolean;
keep_classnames?: boolean | RegExp;
keep_fnames?: boolean | RegExp;
mangle?: boolean | MangleOptions;
module?: boolean;
nameCache?: object;
format?: FormatOptions;
/** @deprecated */
output?: FormatOptions;
parse?: ParseOptions;
safari10?: boolean;
sourceMap?: boolean | SourceMapOptions;
toplevel?: boolean;
};
Default: default
Terser options.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
ecma: undefined,
parse: {},
compress: {},
mangle: true, // Note `mangle.properties` is `false` by default.
module: false,
// Deprecated
output: null,
format: null,
toplevel: false,
nameCache: null,
ie8: false,
keep_classnames: undefined,
keep_fnames: false,
safari10: false,
},
}),
],
},
};
extractComments
Type:
type extractComments =
| boolean
| string
| RegExp
| ((
astNode: any,
comment: {
value: string;
type: "comment1" | "comment2" | "comment3" | "comment4";
pos: number;
line: number;
col: number;
}
) => boolean)
| {
condition?:
| boolean
| "all"
| "some"
| RegExp
| ((
astNode: any,
comment: {
value: string;
type: "comment1" | "comment2" | "comment3" | "comment4";
pos: number;
line: number;
col: number;
}
) => boolean)
| undefined;
filename?: string | ((fileData: any) => string) | undefined;
banner?:
| string
| boolean
| ((commentsFile: string) => string)
| undefined;
};
Default: true
Whether comments shall be extracted to a separate file, (see details).
By default extract only comments using /^\**!|@preserve|@license|@cc_on/i
regexp condition and remove remaining comments.
If the original file is named foo.js
, then the comments will be stored to foo.js.LICENSE.txt
.
The terserOptions.format.comments
option specifies whether the comment will be preserved, i.e. it is possible to preserve some comments (e.g. annotations) while extracting others or even preserving comments that have been extracted.
boolean
Enable/disable extracting comments.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: true,
}),
],
},
};
string
Extract all
or some
(use /^\**!|@preserve|@license|@cc_on/i
RegExp) comments.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: "all",
}),
],
},
};
RegExp
All comments that match the given expression will be extracted to the separate file.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: /@extract/i,
}),
],
},
};
function
All comments that match the given expression will be extracted to the separate file.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: (astNode, comment) => {
if (/@extract/i.test(comment.value)) {
return true;
}
return false;
},
}),
],
},
};
object
Allow to customize condition for extract comments, specify extracted file name and banner.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: {
condition: /^\**!|@preserve|@license|@cc_on/i,
filename: (fileData) => {
// The "fileData" argument contains object with "filename", "basename", "query" and "hash"
return `${fileData.filename}.LICENSE.txt${fileData.query}`;
},
banner: (licenseFile) => {
return `License information can be found in ${licenseFile}`;
},
},
}),
],
},
};
condition
Type:
type condition =
| boolean
| "all"
| "some"
| RegExp
| ((
astNode: any,
comment: {
value: string;
type: "comment1" | "comment2" | "comment3" | "comment4";
pos: number;
line: number;
col: number;
}
) => boolean)
| undefined;
Condition what comments you need extract.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: {
condition: "some",
filename: (fileData) => {
// The "fileData" argument contains object with "filename", "basename", "query" and "hash"
return `${fileData.filename}.LICENSE.txt${fileData.query}`;
},
banner: (licenseFile) => {
return `License information can be found in ${licenseFile}`;
},
},
}),
],
},
};
filename
Type:
type filename = string | ((fileData: any) => string) | undefined;
Default: [file].LICENSE.txt[query]
Available placeholders: [file]
, [query]
and [filebase]
([base]
for webpack 5).
The file where the extracted comments will be stored.
Default is to append the suffix .LICENSE.txt
to the original filename.
Warning
We highly recommend using the
txt
extension. Usingjs
/cjs
/mjs
extensions may conflict with existing assets which leads to broken code.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: {
condition: /^\**!|@preserve|@license|@cc_on/i,
filename: "extracted-comments.js",
banner: (licenseFile) => {
return `License information can be found in ${licenseFile}`;
},
},
}),
],
},
};
banner
Type:
type banner = string | boolean | ((commentsFile: string) => string) | undefined;
Default: /*! For license information please see ${commentsFile} */
The banner text that points to the extracted file and will be added on top of the original file.
Can be false
(no banner), a String
, or a Function<(string) -> String>
that will be called with the filename where extracted comments have been stored.
Will be wrapped into comment.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: {
condition: true,
filename: (fileData) => {
// The "fileData" argument contains object with "filename", "basename", "query" and "hash"
return `${fileData.filename}.LICENSE.txt${fileData.query}`;
},
banner: (commentsFile) => {
return `My custom banner about license information ${commentsFile}`;
},
},
}),
],
},
};
Extract all legal comments (i.e. /^\**!|@preserve|@license|@cc_on/i
) and preserve /@license/i
comments.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
format: {
comments: /@license/i,
},
},
extractComments: true,
}),
],
},
};
If you avoid building with comments, use this config:
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
format: {
comments: false,
},
},
extractComments: false,
}),
],
},
};
uglify-js
UglifyJS
is a JavaScript parser, minifier, compressor and beautifier toolkit.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
minify: TerserPlugin.uglifyJsMinify,
// `terserOptions` options will be passed to `uglify-js`
// Link to options - https://github.com/mishoo/UglifyJS#minify-options
terserOptions: {},
}),
],
},
};
swc
swc
is a super-fast compiler written in rust; producing widely-supported javascript from modern standards and typescript.
Warning
the
extractComments
option is not supported and all comments will be removed by default, it will be fixed in future
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
minify: TerserPlugin.swcMinify,
// `terserOptions` options will be passed to `swc` (`@swc/core`)
// Link to options - https://swc.rs/docs/config-js-minify
terserOptions: {},
}),
],
},
};
esbuild
esbuild
is an extremely fast JavaScript bundler and minifier.
Warning
the
extractComments
option is not supported and all legal comments (i.e. copyright, licenses and etc) will be preserved
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
minify: TerserPlugin.esbuildMinify,
// `terserOptions` options will be passed to `esbuild`
// Link to options - https://esbuild.github.io/api/#minify
// Note: the `minify` options is true by default (and override other `minify*` options), so if you want to disable the `minifyIdentifiers` option (or other `minify*` options) please use:
// terserOptions: {
// minify: false,
// minifyWhitespace: true,
// minifyIdentifiers: false,
// minifySyntax: true,
// },
terserOptions: {},
}),
],
},
};
Override default minify function - use uglify-js
for minification.
webpack.config.js
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
minify: (file, sourceMap) => {
// https://github.com/mishoo/UglifyJS2#minify-options
const uglifyJsOptions = {
/* your `uglify-js` package options */
};
if (sourceMap) {
uglifyJsOptions.sourceMap = {
content: sourceMap,
};
}
return require("uglify-js").minify(file, uglifyJsOptions);
},
}),
],
},
};
With default terser minify function:
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: true,
},
}),
],
},
};
With built-in minify functions:
import type { JsMinifyOptions as SwcOptions } from "@swc/core";
import type { MinifyOptions as UglifyJSOptions } from "uglify-js";
import type { TransformOptions as EsbuildOptions } from "esbuild";
import type { MinifyOptions as TerserOptions } from "terser";
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin<SwcOptions>({
minify: TerserPlugin.swcMinify,
terserOptions: {
// `swc` options
},
}),
new TerserPlugin<UglifyJSOptions>({
minify: TerserPlugin.uglifyJsMinify,
terserOptions: {
// `uglif-js` options
},
}),
new TerserPlugin<EsbuildOptions>({
minify: TerserPlugin.esbuildMinify,
terserOptions: {
// `esbuild` options
},
}),
// Alternative usage:
new TerserPlugin<TerserOptions>({
minify: TerserPlugin.terserMinify,
terserOptions: {
// `terser` options
},
}),
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
watch 모드인 경우, 제공된 경로나 정규 표현식에 해당되는 특정 파일을 무시합니다.
new webpack.WatchIgnorePlugin({ paths });
paths
(Array<string | RegExp>
): 무시해야 하는 디렉터리나 파일에 대한 정규 표현식 또는 절대 경로의 목록입니다.