1 | <div align="center">
|
2 | <a href="https://github.com/webpack/webpack">
|
3 | <img width="200" height="200" src="https://webpack.js.org/assets/icon-square-big.svg">
|
4 | </a>
|
5 | </div>
|
6 |
|
7 | [![npm][npm]][npm-url]
|
8 | [![node][node]][node-url]
|
9 | [![tests][tests]][tests-url]
|
10 | [![cover][cover]][cover-url]
|
11 | [![discussion][discussion]][discussion-url]
|
12 | [![size][size]][size-url]
|
13 |
|
14 | # compression-webpack-plugin
|
15 |
|
16 | Prepare compressed versions of assets to serve them with Content-Encoding.
|
17 |
|
18 | ## Getting Started
|
19 |
|
20 | To begin, you'll need to install `compression-webpack-plugin`:
|
21 |
|
22 | ```console
|
23 | npm install compression-webpack-plugin --save-dev
|
24 | ```
|
25 |
|
26 | or
|
27 |
|
28 | ```console
|
29 | yarn add -D compression-webpack-plugin
|
30 | ```
|
31 |
|
32 | or
|
33 |
|
34 | ```console
|
35 | pnpm add -D compression-webpack-plugin
|
36 | ```
|
37 |
|
38 | Then add the plugin to your `webpack` config. For example:
|
39 |
|
40 | **webpack.config.js**
|
41 |
|
42 | ```js
|
43 | const CompressionPlugin = require("compression-webpack-plugin");
|
44 |
|
45 | module.exports = {
|
46 | plugins: [new CompressionPlugin()],
|
47 | };
|
48 | ```
|
49 |
|
50 | And run `webpack` via your preferred method.
|
51 |
|
52 | ## Options
|
53 |
|
54 | - **[`test`](#test)**
|
55 | - **[`include`](#include)**
|
56 | - **[`exclude`](#exclude)**
|
57 | - **[`algorithm`](#algorithm)**
|
58 | - **[`compressionOptions`](#compressionoptions)**
|
59 | - **[`threshold`](#threshold)**
|
60 | - **[`minRatio`](#minratio)**
|
61 | - **[`filename`](#filename)**
|
62 | - **[`deleteOriginalAssets`](#deleteoriginalassets)**
|
63 |
|
64 | ### `test`
|
65 |
|
66 | Type:
|
67 |
|
68 | ```ts
|
69 | type test = string | RegExp | Array<string | RegExp>;
|
70 | ```
|
71 |
|
72 | Default: `undefined`
|
73 |
|
74 | Include all assets that pass test assertion.
|
75 |
|
76 | **webpack.config.js**
|
77 |
|
78 | ```js
|
79 | module.exports = {
|
80 | plugins: [
|
81 | new CompressionPlugin({
|
82 | test: /\.js(\?.*)?$/i,
|
83 | }),
|
84 | ],
|
85 | };
|
86 | ```
|
87 |
|
88 | ### `include`
|
89 |
|
90 | Type:
|
91 |
|
92 | ```ts
|
93 | type include = string | RegExp | Array<string | RegExp>;
|
94 | ```
|
95 |
|
96 | Default: `undefined`
|
97 |
|
98 | Include all assets matching any of these conditions.
|
99 |
|
100 | **webpack.config.js**
|
101 |
|
102 | ```js
|
103 | module.exports = {
|
104 | plugins: [
|
105 | new CompressionPlugin({
|
106 | include: /\/includes/,
|
107 | }),
|
108 | ],
|
109 | };
|
110 | ```
|
111 |
|
112 | ### `exclude`
|
113 |
|
114 | Type:
|
115 |
|
116 | ```ts
|
117 | type exclude = string | RegExp | Array<string | RegExp>;
|
118 | ```
|
119 |
|
120 | Default: `undefined`
|
121 |
|
122 | Exclude all assets matching any of these conditions.
|
123 |
|
124 | **webpack.config.js**
|
125 |
|
126 | ```js
|
127 | module.exports = {
|
128 | plugins: [
|
129 | new CompressionPlugin({
|
130 | exclude: /\/excludes/,
|
131 | }),
|
132 | ],
|
133 | };
|
134 | ```
|
135 |
|
136 | ### `algorithm`
|
137 |
|
138 | Type:
|
139 |
|
140 | ```ts
|
141 | type algorithm =
|
142 | | string
|
143 | | ((
|
144 | input: Buffer,
|
145 | options: CompressionOptions,
|
146 | callback: (
|
147 | error: Error | null | undefined,
|
148 | result:
|
149 | | string
|
150 | | ArrayBuffer
|
151 | | SharedArrayBuffer
|
152 | | Uint8Array
|
153 | | readonly number[]
|
154 | | {
|
155 | valueOf(): ArrayBuffer | SharedArrayBuffer;
|
156 | }
|
157 | | {
|
158 | valueOf(): string | Uint8Array | readonly number[];
|
159 | }
|
160 | | {
|
161 | valueOf(): string;
|
162 | }
|
163 | | {
|
164 | [Symbol.toPrimitive](hint: "string"): string;
|
165 | },
|
166 | ) => void,
|
167 | ) => any);
|
168 | ```
|
169 |
|
170 | Default: `gzip`
|
171 |
|
172 | The compression algorithm/function.
|
173 |
|
174 | > **Note**
|
175 | >
|
176 | > If you use custom function for the `algorithm` option, the default value of the `compressionOptions` option is `{}`.
|
177 |
|
178 | #### `string`
|
179 |
|
180 | The algorithm is taken from [zlib](https://nodejs.org/api/zlib.html).
|
181 |
|
182 | **webpack.config.js**
|
183 |
|
184 | ```js
|
185 | module.exports = {
|
186 | plugins: [
|
187 | new CompressionPlugin({
|
188 | algorithm: "gzip",
|
189 | }),
|
190 | ],
|
191 | };
|
192 | ```
|
193 |
|
194 | #### `function`
|
195 |
|
196 | Allow to specify a custom compression function.
|
197 |
|
198 | **webpack.config.js**
|
199 |
|
200 | ```js
|
201 | module.exports = {
|
202 | plugins: [
|
203 | new CompressionPlugin({
|
204 | algorithm(input, compressionOptions, callback) {
|
205 | return compressionFunction(input, compressionOptions, callback);
|
206 | },
|
207 | }),
|
208 | ],
|
209 | };
|
210 | ```
|
211 |
|
212 | ### `compressionOptions`
|
213 |
|
214 | Type:
|
215 |
|
216 | ```ts
|
217 | type compressionOptions = {
|
218 | flush?: number;
|
219 | finishFlush?: number;
|
220 | chunkSize?: number;
|
221 | windowBits?: number;
|
222 | level?: number;
|
223 | memLevel?: number;
|
224 | strategy?: number;
|
225 | dictionary?: Buffer | TypedArray | DataView | ArrayBuffer;
|
226 | info?: boolean;
|
227 | maxOutputLength?: number;
|
228 | };
|
229 | ```
|
230 |
|
231 | Default: `{ level: 9 }`
|
232 |
|
233 | Compression options for `algorithm`.
|
234 |
|
235 | You can find all options here [zlib](https://nodejs.org/api/zlib.html#zlib_class_options).
|
236 |
|
237 | > **Note**
|
238 | >
|
239 | > If you use custom function for the `algorithm` option, the default value is `{}`.
|
240 |
|
241 | **webpack.config.js**
|
242 |
|
243 | ```js
|
244 | module.exports = {
|
245 | plugins: [
|
246 | new CompressionPlugin({
|
247 | compressionOptions: { level: 1 },
|
248 | }),
|
249 | ],
|
250 | };
|
251 | ```
|
252 |
|
253 | ### `threshold`
|
254 |
|
255 | Type:
|
256 |
|
257 | ```ts
|
258 | type threshold = number;
|
259 | ```
|
260 |
|
261 | Default: `0`
|
262 |
|
263 | Only assets bigger than this size are processed. In bytes.
|
264 |
|
265 | **webpack.config.js**
|
266 |
|
267 | ```js
|
268 | module.exports = {
|
269 | plugins: [
|
270 | new CompressionPlugin({
|
271 | threshold: 8192,
|
272 | }),
|
273 | ],
|
274 | };
|
275 | ```
|
276 |
|
277 | ### `minRatio`
|
278 |
|
279 | Type:
|
280 |
|
281 | ```ts
|
282 | type minRatio = number;
|
283 | ```
|
284 |
|
285 | Default: `0.8`
|
286 |
|
287 | Only assets that compress better than this ratio are processed (`minRatio = Compressed Size / Original Size`).
|
288 | Example: you have `image.png` file with 1024b size, compressed version of file has 768b size, so `minRatio` equal `0.75`.
|
289 | In other words assets will be processed when the `Compressed Size / Original Size` value less `minRatio` value.
|
290 |
|
291 | You can use `1` value to process assets that are smaller than the original.
|
292 |
|
293 | 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).
|
294 |
|
295 | 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.
|
296 |
|
297 | **webpack.config.js**
|
298 |
|
299 | ```js
|
300 | module.exports = {
|
301 | plugins: [
|
302 | new CompressionPlugin({
|
303 | // Compress all assets, including files with `0` bytes size
|
304 | // minRatio: Infinity
|
305 |
|
306 | // Compress all assets, excluding files with `0` bytes size
|
307 | // minRatio: Number.MAX_SAFE_INTEGER
|
308 |
|
309 | minRatio: 0.8,
|
310 | }),
|
311 | ],
|
312 | };
|
313 | ```
|
314 |
|
315 | ### `filename`
|
316 |
|
317 | Type:
|
318 |
|
319 | ```ts
|
320 | type filename = string | ((pathdata: PathData) => string);
|
321 | ```
|
322 |
|
323 | Default: `"[path][base].gz"`
|
324 |
|
325 | The target asset filename.
|
326 |
|
327 | #### `string`
|
328 |
|
329 | For example we have `assets/images/image.png?foo=bar#hash`:
|
330 |
|
331 | `[path]` is replaced with the directories to the original asset, included trailing `/` (`assets/images/`).
|
332 |
|
333 | `[file]` is replaced with the path of original asset (`assets/images/image.png`).
|
334 |
|
335 | `[base]` is replaced with the base (`[name]` + `[ext]`) of the original asset (`image.png`).
|
336 |
|
337 | `[name]` is replaced with the name of the original asset (`image`).
|
338 |
|
339 | `[ext]` is replaced with the extension of the original asset, included `.` (`.png`).
|
340 |
|
341 | `[query]` is replaced with the query of the original asset, included `?` (`?foo=bar`).
|
342 |
|
343 | `[fragment]` is replaced with the fragment (in the concept of URL it is called `hash`) of the original asset (`#hash`).
|
344 |
|
345 | **webpack.config.js**
|
346 |
|
347 | ```js
|
348 | module.exports = {
|
349 | plugins: [
|
350 | new CompressionPlugin({
|
351 | filename: "[path][base].gz",
|
352 | }),
|
353 | ],
|
354 | };
|
355 | ```
|
356 |
|
357 | #### `function`
|
358 |
|
359 | **webpack.config.js**
|
360 |
|
361 | ```js
|
362 | module.exports = {
|
363 | plugins: [
|
364 | new CompressionPlugin({
|
365 | filename(pathData) {
|
366 | // The `pathData` argument contains all placeholders - `path`/`name`/`ext`/etc
|
367 | // Available properties described above, for the `String` notation
|
368 | if (/\.svg$/.test(pathData.filename)) {
|
369 | return "assets/svg/[path][base].gz";
|
370 | }
|
371 |
|
372 | return "assets/js/[path][base].gz";
|
373 | },
|
374 | }),
|
375 | ],
|
376 | };
|
377 | ```
|
378 |
|
379 | ### `deleteOriginalAssets`
|
380 |
|
381 | Type:
|
382 |
|
383 | ```ts
|
384 | type deleteOriginalAssets =
|
385 | | boolean
|
386 | | "keep-source-map"
|
387 | | ((name: string) => boolean);
|
388 | ```
|
389 |
|
390 | Default: `false`
|
391 |
|
392 | Whether to delete the original assets or not.
|
393 |
|
394 | **webpack.config.js**
|
395 |
|
396 | ```js
|
397 | module.exports = {
|
398 | plugins: [
|
399 | new CompressionPlugin({
|
400 | deleteOriginalAssets: true,
|
401 | }),
|
402 | ],
|
403 | };
|
404 | ```
|
405 |
|
406 | To exclude sourcemaps from compression:
|
407 |
|
408 | ```js
|
409 | module.exports = {
|
410 | plugins: [
|
411 | new CompressionPlugin({
|
412 | exclude: /.map$/,
|
413 | deleteOriginalAssets: "keep-source-map",
|
414 | }),
|
415 | ],
|
416 | };
|
417 | ```
|
418 |
|
419 | Using a custom function:
|
420 |
|
421 | ```js
|
422 | module.exports = {
|
423 | plugins: [
|
424 | new CompressionPlugin({
|
425 | exclude: /.map$/,
|
426 | deleteOriginalAssets: (name) => {
|
427 | if (/\.js$/.test(name)) {
|
428 | return false;
|
429 | }
|
430 |
|
431 | return true;
|
432 | },
|
433 | }),
|
434 | ],
|
435 | };
|
436 | ```
|
437 |
|
438 | ## Examples
|
439 |
|
440 | ### Using Zopfli
|
441 |
|
442 | Prepare compressed versions of assets using `zopfli` library.
|
443 |
|
444 | > **Note**
|
445 | >
|
446 | > `@gfx/zopfli` require minimum `8` version of `node`.
|
447 |
|
448 | To begin, you'll need to install `@gfx/zopfli`:
|
449 |
|
450 | ```console
|
451 | $ npm install @gfx/zopfli --save-dev
|
452 | ```
|
453 |
|
454 | **webpack.config.js**
|
455 |
|
456 | ```js
|
457 | const zopfli = require("@gfx/zopfli");
|
458 |
|
459 | module.exports = {
|
460 | plugins: [
|
461 | new CompressionPlugin({
|
462 | compressionOptions: {
|
463 | numiterations: 15,
|
464 | },
|
465 | algorithm(input, compressionOptions, callback) {
|
466 | return zopfli.gzip(input, compressionOptions, callback);
|
467 | },
|
468 | }),
|
469 | ],
|
470 | };
|
471 | ```
|
472 |
|
473 | ### Using Brotli
|
474 |
|
475 | [Brotli](https://en.wikipedia.org/wiki/Brotli) is a compression algorithm originally developed by Google, and offers compression superior to gzip.
|
476 |
|
477 | Node 10.16.0 and later has [native support](https://nodejs.org/api/zlib.html#zlib_zlib_createbrotlicompress_options) for Brotli compression in its zlib module.
|
478 |
|
479 | 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:
|
480 |
|
481 | **webpack.config.js**
|
482 |
|
483 | ```js
|
484 | const zlib = require("zlib");
|
485 |
|
486 | module.exports = {
|
487 | plugins: [
|
488 | new CompressionPlugin({
|
489 | filename: "[path][base].br",
|
490 | algorithm: "brotliCompress",
|
491 | test: /\.(js|css|html|svg)$/,
|
492 | compressionOptions: {
|
493 | params: {
|
494 | [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
|
495 | },
|
496 | },
|
497 | threshold: 10240,
|
498 | minRatio: 0.8,
|
499 | deleteOriginalAssets: false,
|
500 | }),
|
501 | ],
|
502 | };
|
503 | ```
|
504 |
|
505 | **Note** Brotli’s `BROTLI_PARAM_QUALITY` option is functionally equivalent to zlib’s `level` option.
|
506 | You can find all Brotli’s options in [the relevant part of the zlib module documentation](https://nodejs.org/api/zlib.html#zlib_class_brotlioptions).
|
507 |
|
508 | ### Multiple compressed versions of assets for different algorithm
|
509 |
|
510 | **webpack.config.js**
|
511 |
|
512 | ```js
|
513 | const zlib = require("zlib");
|
514 |
|
515 | module.exports = {
|
516 | plugins: [
|
517 | new CompressionPlugin({
|
518 | filename: "[path][base].gz",
|
519 | algorithm: "gzip",
|
520 | test: /\.js$|\.css$|\.html$/,
|
521 | threshold: 10240,
|
522 | minRatio: 0.8,
|
523 | }),
|
524 | new CompressionPlugin({
|
525 | filename: "[path][base].br",
|
526 | algorithm: "brotliCompress",
|
527 | test: /\.(js|css|html|svg)$/,
|
528 | compressionOptions: {
|
529 | params: {
|
530 | [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
|
531 | },
|
532 | },
|
533 | threshold: 10240,
|
534 | minRatio: 0.8,
|
535 | }),
|
536 | ],
|
537 | };
|
538 | ```
|
539 |
|
540 | ## Contributing
|
541 |
|
542 | Please take a moment to read our contributing guidelines if you haven't yet done so.
|
543 |
|
544 | [CONTRIBUTING](./.github/CONTRIBUTING.md)
|
545 |
|
546 | ## License
|
547 |
|
548 | [MIT](./LICENSE)
|
549 |
|
550 | [npm]: https://img.shields.io/npm/v/compression-webpack-plugin.svg
|
551 | [npm-url]: https://npmjs.com/package/compression-webpack-plugin
|
552 | [node]: https://img.shields.io/node/v/compression-webpack-plugin.svg
|
553 | [node-url]: https://nodejs.org
|
554 | [tests]: https://github.com/webpack-contrib/compression-webpack-plugin/workflows/compression-webpack-plugin/badge.svg
|
555 | [tests-url]: https://github.com/webpack-contrib/compression-webpack-plugin/actions
|
556 | [cover]: https://codecov.io/gh/webpack-contrib/compression-webpack-plugin/branch/master/graph/badge.svg
|
557 | [cover-url]: https://codecov.io/gh/webpack-contrib/compression-webpack-plugin
|
558 | [discussion]: https://img.shields.io/github/discussions/webpack/webpack
|
559 | [discussion-url]: https://github.com/webpack/webpack/discussions
|
560 | [size]: https://packagephobia.now.sh/badge?p=compression-webpack-plugin
|
561 | [size-url]: https://packagephobia.now.sh/result?p=compression-webpack-plugin
|