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 | [![chat][chat]][chat-url]
|
12 | [![size][size]][size-url]
|
13 |
|
14 | # terser-webpack-plugin
|
15 |
|
16 | This plugin uses [terser](https://github.com/terser/terser) to minify/minimize your JavaScript.
|
17 |
|
18 | ## Getting Started
|
19 |
|
20 | 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.
|
21 |
|
22 | To begin, you'll need to install `terser-webpack-plugin`:
|
23 |
|
24 | ```console
|
25 | npm install terser-webpack-plugin --save-dev
|
26 | ```
|
27 |
|
28 | or
|
29 |
|
30 | ```console
|
31 | yarn add -D terser-webpack-plugin
|
32 | ```
|
33 |
|
34 | or
|
35 |
|
36 | ```console
|
37 | pnpm add -D terser-webpack-plugin
|
38 | ```
|
39 |
|
40 | Then add the plugin to your `webpack` config. For example:
|
41 |
|
42 | **webpack.config.js**
|
43 |
|
44 | ```js
|
45 | const TerserPlugin = require("terser-webpack-plugin");
|
46 |
|
47 | module.exports = {
|
48 | optimization: {
|
49 | minimize: true,
|
50 | minimizer: [new TerserPlugin()],
|
51 | },
|
52 | };
|
53 | ```
|
54 |
|
55 | And run `webpack` via your preferred method.
|
56 |
|
57 | ## Note about source maps
|
58 |
|
59 | **Works only with `source-map`, `inline-source-map`, `hidden-source-map` and `nosources-source-map` values for the [`devtool`](https://webpack.js.org/configuration/devtool/) option.**
|
60 |
|
61 | Why?
|
62 |
|
63 | - `eval` wraps modules in `eval("string")` and the minimizer does not handle strings.
|
64 | - `cheap` has not column information and minimizer generate only a single line, which leave only a single mapping.
|
65 |
|
66 | Using supported `devtool` values enable source map generation.
|
67 |
|
68 | ## Options
|
69 |
|
70 | - **[`test`](#test)**
|
71 | - **[`include`](#include)**
|
72 | - **[`exclude`](#exclude)**
|
73 | - **[`parallel`](#parallel)**
|
74 | - **[`minify`](#minify)**
|
75 | - **[`terserOptions`](#terseroptions)**
|
76 | - **[`extractComments`](#extractcomments)**
|
77 |
|
78 | ### `test`
|
79 |
|
80 | Type:
|
81 |
|
82 | ```ts
|
83 | type test = string | RegExp | Array<string | RegExp>;
|
84 | ```
|
85 |
|
86 | Default: `/\.m?js(\?.*)?$/i`
|
87 |
|
88 | Test to match files against.
|
89 |
|
90 | **webpack.config.js**
|
91 |
|
92 | ```js
|
93 | module.exports = {
|
94 | optimization: {
|
95 | minimize: true,
|
96 | minimizer: [
|
97 | new TerserPlugin({
|
98 | test: /\.js(\?.*)?$/i,
|
99 | }),
|
100 | ],
|
101 | },
|
102 | };
|
103 | ```
|
104 |
|
105 | ### `include`
|
106 |
|
107 | Type:
|
108 |
|
109 | ```ts
|
110 | type include = string | RegExp | Array<string | RegExp>;
|
111 | ```
|
112 |
|
113 | Default: `undefined`
|
114 |
|
115 | Files to include.
|
116 |
|
117 | **webpack.config.js**
|
118 |
|
119 | ```js
|
120 | module.exports = {
|
121 | optimization: {
|
122 | minimize: true,
|
123 | minimizer: [
|
124 | new TerserPlugin({
|
125 | include: /\/includes/,
|
126 | }),
|
127 | ],
|
128 | },
|
129 | };
|
130 | ```
|
131 |
|
132 | ### `exclude`
|
133 |
|
134 | Type:
|
135 |
|
136 | ```ts
|
137 | type exclude = string | RegExp | Array<string | RegExp>;
|
138 | ```
|
139 |
|
140 | Default: `undefined`
|
141 |
|
142 | Files to exclude.
|
143 |
|
144 | **webpack.config.js**
|
145 |
|
146 | ```js
|
147 | module.exports = {
|
148 | optimization: {
|
149 | minimize: true,
|
150 | minimizer: [
|
151 | new TerserPlugin({
|
152 | exclude: /\/excludes/,
|
153 | }),
|
154 | ],
|
155 | },
|
156 | };
|
157 | ```
|
158 |
|
159 | ### `parallel`
|
160 |
|
161 | Type:
|
162 |
|
163 | ```ts
|
164 | type parallel = boolean | number;
|
165 | ```
|
166 |
|
167 | Default: `true`
|
168 |
|
169 | Use multi-process parallel running to improve the build speed.
|
170 | Default number of concurrent runs: `os.cpus().length - 1`.
|
171 |
|
172 | > ℹ️ Parallelization can speedup your build significantly and is therefore **highly recommended**.
|
173 |
|
174 | > ⚠️ 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](https://github.com/webpack-contrib/terser-webpack-plugin/issues/143), [#202](https://github.com/webpack-contrib/terser-webpack-plugin/issues/202)).
|
175 |
|
176 | #### `boolean`
|
177 |
|
178 | Enable/disable multi-process parallel running.
|
179 |
|
180 | **webpack.config.js**
|
181 |
|
182 | ```js
|
183 | module.exports = {
|
184 | optimization: {
|
185 | minimize: true,
|
186 | minimizer: [
|
187 | new TerserPlugin({
|
188 | parallel: true,
|
189 | }),
|
190 | ],
|
191 | },
|
192 | };
|
193 | ```
|
194 |
|
195 | #### `number`
|
196 |
|
197 | Enable multi-process parallel running and set number of concurrent runs.
|
198 |
|
199 | **webpack.config.js**
|
200 |
|
201 | ```js
|
202 | module.exports = {
|
203 | optimization: {
|
204 | minimize: true,
|
205 | minimizer: [
|
206 | new TerserPlugin({
|
207 | parallel: 4,
|
208 | }),
|
209 | ],
|
210 | },
|
211 | };
|
212 | ```
|
213 |
|
214 | ### `minify`
|
215 |
|
216 | Type:
|
217 |
|
218 | ```ts
|
219 | type minify = (
|
220 | input: {
|
221 | [file: string]: string;
|
222 | },
|
223 | sourceMap: import("@jridgewell/trace-mapping").SourceMapInput | undefined,
|
224 | minifyOptions: {
|
225 | module?: boolean | undefined;
|
226 | ecma?: import("terser").ECMA | undefined;
|
227 | },
|
228 | extractComments:
|
229 | | boolean
|
230 | | "all"
|
231 | | "some"
|
232 | | RegExp
|
233 | | ((
|
234 | astNode: any,
|
235 | comment: {
|
236 | value: string;
|
237 | type: "comment1" | "comment2" | "comment3" | "comment4";
|
238 | pos: number;
|
239 | line: number;
|
240 | col: number;
|
241 | }
|
242 | ) => boolean)
|
243 | | {
|
244 | condition?:
|
245 | | boolean
|
246 | | "all"
|
247 | | "some"
|
248 | | RegExp
|
249 | | ((
|
250 | astNode: any,
|
251 | comment: {
|
252 | value: string;
|
253 | type: "comment1" | "comment2" | "comment3" | "comment4";
|
254 | pos: number;
|
255 | line: number;
|
256 | col: number;
|
257 | }
|
258 | ) => boolean)
|
259 | | undefined;
|
260 | filename?: string | ((fileData: any) => string) | undefined;
|
261 | banner?:
|
262 | | string
|
263 | | boolean
|
264 | | ((commentsFile: string) => string)
|
265 | | undefined;
|
266 | }
|
267 | | undefined
|
268 | ) => Promise<{
|
269 | code: string;
|
270 | map?: import("@jridgewell/trace-mapping").SourceMapInput | undefined;
|
271 | errors?: (string | Error)[] | undefined;
|
272 | warnings?: (string | Error)[] | undefined;
|
273 | extractedComments?: string[] | undefined;
|
274 | }>;
|
275 | ```
|
276 |
|
277 | Default: `TerserPlugin.terserMinify`
|
278 |
|
279 | Allows you to override default minify function.
|
280 | By default plugin uses [terser](https://github.com/terser/terser) package.
|
281 | Useful for using and testing unpublished versions or forks.
|
282 |
|
283 | > ⚠️ **Always use `require` inside `minify` function when `parallel` option enabled**.
|
284 |
|
285 | **webpack.config.js**
|
286 |
|
287 | ```js
|
288 | // Can be async
|
289 | const minify = (input, sourceMap, minimizerOptions, extractsComments) => {
|
290 | // The `minimizerOptions` option contains option from the `terserOptions` option
|
291 | // You can use `minimizerOptions.myCustomOption`
|
292 |
|
293 | // Custom logic for extract comments
|
294 | const { map, code } = require("uglify-module") // Or require('./path/to/uglify-module')
|
295 | .minify(input, {
|
296 | /* Your options for minification */
|
297 | });
|
298 |
|
299 | return { map, code, warnings: [], errors: [], extractedComments: [] };
|
300 | };
|
301 |
|
302 | // Used to regenerate `fullhash`/`chunkhash` between different implementation
|
303 | // 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
|
304 | // to avoid this you can provide version of your custom minimizer
|
305 | // You don't need if you use only `contenthash`
|
306 | minify.getMinimizerVersion = () => {
|
307 | let packageJson;
|
308 |
|
309 | try {
|
310 | // eslint-disable-next-line global-require, import/no-extraneous-dependencies
|
311 | packageJson = require("uglify-module/package.json");
|
312 | } catch (error) {
|
313 | // Ignore
|
314 | }
|
315 |
|
316 | return packageJson && packageJson.version;
|
317 | };
|
318 |
|
319 | module.exports = {
|
320 | optimization: {
|
321 | minimize: true,
|
322 | minimizer: [
|
323 | new TerserPlugin({
|
324 | terserOptions: {
|
325 | myCustomOption: true,
|
326 | },
|
327 | minify,
|
328 | }),
|
329 | ],
|
330 | },
|
331 | };
|
332 | ```
|
333 |
|
334 | ### `terserOptions`
|
335 |
|
336 | Type:
|
337 |
|
338 | ```ts
|
339 | type terserOptions = {
|
340 | compress?: boolean | CompressOptions;
|
341 | ecma?: ECMA;
|
342 | enclose?: boolean | string;
|
343 | ie8?: boolean;
|
344 | keep_classnames?: boolean | RegExp;
|
345 | keep_fnames?: boolean | RegExp;
|
346 | mangle?: boolean | MangleOptions;
|
347 | module?: boolean;
|
348 | nameCache?: object;
|
349 | format?: FormatOptions;
|
350 | /** @deprecated */
|
351 | output?: FormatOptions;
|
352 | parse?: ParseOptions;
|
353 | safari10?: boolean;
|
354 | sourceMap?: boolean | SourceMapOptions;
|
355 | toplevel?: boolean;
|
356 | };
|
357 | ```
|
358 |
|
359 | Default: [default](https://github.com/terser/terser#minify-options)
|
360 |
|
361 | Terser [options](https://github.com/terser/terser#minify-options).
|
362 |
|
363 | **webpack.config.js**
|
364 |
|
365 | ```js
|
366 | module.exports = {
|
367 | optimization: {
|
368 | minimize: true,
|
369 | minimizer: [
|
370 | new TerserPlugin({
|
371 | terserOptions: {
|
372 | ecma: undefined,
|
373 | parse: {},
|
374 | compress: {},
|
375 | mangle: true, // Note `mangle.properties` is `false` by default.
|
376 | module: false,
|
377 | // Deprecated
|
378 | output: null,
|
379 | format: null,
|
380 | toplevel: false,
|
381 | nameCache: null,
|
382 | ie8: false,
|
383 | keep_classnames: undefined,
|
384 | keep_fnames: false,
|
385 | safari10: false,
|
386 | },
|
387 | }),
|
388 | ],
|
389 | },
|
390 | };
|
391 | ```
|
392 |
|
393 | ### `extractComments`
|
394 |
|
395 | Type:
|
396 |
|
397 | ```ts
|
398 | type extractComments =
|
399 | | boolean
|
400 | | string
|
401 | | RegExp
|
402 | | ((
|
403 | astNode: any,
|
404 | comment: {
|
405 | value: string;
|
406 | type: "comment1" | "comment2" | "comment3" | "comment4";
|
407 | pos: number;
|
408 | line: number;
|
409 | col: number;
|
410 | }
|
411 | ) => boolean)
|
412 | | {
|
413 | condition?:
|
414 | | boolean
|
415 | | "all"
|
416 | | "some"
|
417 | | RegExp
|
418 | | ((
|
419 | astNode: any,
|
420 | comment: {
|
421 | value: string;
|
422 | type: "comment1" | "comment2" | "comment3" | "comment4";
|
423 | pos: number;
|
424 | line: number;
|
425 | col: number;
|
426 | }
|
427 | ) => boolean)
|
428 | | undefined;
|
429 | filename?: string | ((fileData: any) => string) | undefined;
|
430 | banner?:
|
431 | | string
|
432 | | boolean
|
433 | | ((commentsFile: string) => string)
|
434 | | undefined;
|
435 | };
|
436 | ```
|
437 |
|
438 | Default: `true`
|
439 |
|
440 | Whether comments shall be extracted to a separate file, (see [details](https://github.com/webpack/webpack/commit/71933e979e51c533b432658d5e37917f9e71595a)).
|
441 | By default extract only comments using `/^\**!|@preserve|@license|@cc_on/i` regexp condition and remove remaining comments.
|
442 | If the original file is named `foo.js`, then the comments will be stored to `foo.js.LICENSE.txt`.
|
443 | 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.
|
444 |
|
445 | #### `boolean`
|
446 |
|
447 | Enable/disable extracting comments.
|
448 |
|
449 | **webpack.config.js**
|
450 |
|
451 | ```js
|
452 | module.exports = {
|
453 | optimization: {
|
454 | minimize: true,
|
455 | minimizer: [
|
456 | new TerserPlugin({
|
457 | extractComments: true,
|
458 | }),
|
459 | ],
|
460 | },
|
461 | };
|
462 | ```
|
463 |
|
464 | #### `string`
|
465 |
|
466 | Extract `all` or `some` (use `/^\**!|@preserve|@license|@cc_on/i` RegExp) comments.
|
467 |
|
468 | **webpack.config.js**
|
469 |
|
470 | ```js
|
471 | module.exports = {
|
472 | optimization: {
|
473 | minimize: true,
|
474 | minimizer: [
|
475 | new TerserPlugin({
|
476 | extractComments: "all",
|
477 | }),
|
478 | ],
|
479 | },
|
480 | };
|
481 | ```
|
482 |
|
483 | #### `RegExp`
|
484 |
|
485 | All comments that match the given expression will be extracted to the separate file.
|
486 |
|
487 | **webpack.config.js**
|
488 |
|
489 | ```js
|
490 | module.exports = {
|
491 | optimization: {
|
492 | minimize: true,
|
493 | minimizer: [
|
494 | new TerserPlugin({
|
495 | extractComments: /@extract/i,
|
496 | }),
|
497 | ],
|
498 | },
|
499 | };
|
500 | ```
|
501 |
|
502 | #### `function`
|
503 |
|
504 | All comments that match the given expression will be extracted to the separate file.
|
505 |
|
506 | **webpack.config.js**
|
507 |
|
508 | ```js
|
509 | module.exports = {
|
510 | optimization: {
|
511 | minimize: true,
|
512 | minimizer: [
|
513 | new TerserPlugin({
|
514 | extractComments: (astNode, comment) => {
|
515 | if (/@extract/i.test(comment.value)) {
|
516 | return true;
|
517 | }
|
518 |
|
519 | return false;
|
520 | },
|
521 | }),
|
522 | ],
|
523 | },
|
524 | };
|
525 | ```
|
526 |
|
527 | #### `object`
|
528 |
|
529 | Allow to customize condition for extract comments, specify extracted file name and banner.
|
530 |
|
531 | **webpack.config.js**
|
532 |
|
533 | ```js
|
534 | module.exports = {
|
535 | optimization: {
|
536 | minimize: true,
|
537 | minimizer: [
|
538 | new TerserPlugin({
|
539 | extractComments: {
|
540 | condition: /^\**!|@preserve|@license|@cc_on/i,
|
541 | filename: (fileData) => {
|
542 | // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
|
543 | return `${fileData.filename}.LICENSE.txt${fileData.query}`;
|
544 | },
|
545 | banner: (licenseFile) => {
|
546 | return `License information can be found in ${licenseFile}`;
|
547 | },
|
548 | },
|
549 | }),
|
550 | ],
|
551 | },
|
552 | };
|
553 | ```
|
554 |
|
555 | ##### `condition`
|
556 |
|
557 | Type:
|
558 |
|
559 | ```ts
|
560 | type condition =
|
561 | | boolean
|
562 | | "all"
|
563 | | "some"
|
564 | | RegExp
|
565 | | ((
|
566 | astNode: any,
|
567 | comment: {
|
568 | value: string;
|
569 | type: "comment1" | "comment2" | "comment3" | "comment4";
|
570 | pos: number;
|
571 | line: number;
|
572 | col: number;
|
573 | }
|
574 | ) => boolean)
|
575 | | undefined;
|
576 | ```
|
577 |
|
578 | Condition what comments you need extract.
|
579 |
|
580 | **webpack.config.js**
|
581 |
|
582 | ```js
|
583 | module.exports = {
|
584 | optimization: {
|
585 | minimize: true,
|
586 | minimizer: [
|
587 | new TerserPlugin({
|
588 | extractComments: {
|
589 | condition: "some",
|
590 | filename: (fileData) => {
|
591 | // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
|
592 | return `${fileData.filename}.LICENSE.txt${fileData.query}`;
|
593 | },
|
594 | banner: (licenseFile) => {
|
595 | return `License information can be found in ${licenseFile}`;
|
596 | },
|
597 | },
|
598 | }),
|
599 | ],
|
600 | },
|
601 | };
|
602 | ```
|
603 |
|
604 | ##### `filename`
|
605 |
|
606 | Type:
|
607 |
|
608 | ```ts
|
609 | type filename = string | ((fileData: any) => string) | undefined;
|
610 | ```
|
611 |
|
612 | Default: `[file].LICENSE.txt[query]`
|
613 |
|
614 | Available placeholders: `[file]`, `[query]` and `[filebase]` (`[base]` for webpack 5).
|
615 |
|
616 | The file where the extracted comments will be stored.
|
617 | Default is to append the suffix `.LICENSE.txt` to the original filename.
|
618 |
|
619 | > ⚠️ We highly recommend using the `txt` extension. Using `js`/`cjs`/`mjs` extensions may conflict with existing assets which leads to broken code.
|
620 |
|
621 | **webpack.config.js**
|
622 |
|
623 | ```js
|
624 | module.exports = {
|
625 | optimization: {
|
626 | minimize: true,
|
627 | minimizer: [
|
628 | new TerserPlugin({
|
629 | extractComments: {
|
630 | condition: /^\**!|@preserve|@license|@cc_on/i,
|
631 | filename: "extracted-comments.js",
|
632 | banner: (licenseFile) => {
|
633 | return `License information can be found in ${licenseFile}`;
|
634 | },
|
635 | },
|
636 | }),
|
637 | ],
|
638 | },
|
639 | };
|
640 | ```
|
641 |
|
642 | ##### `banner`
|
643 |
|
644 | Type:
|
645 |
|
646 | ```ts
|
647 | type banner = string | boolean | ((commentsFile: string) => string) | undefined;
|
648 | ```
|
649 |
|
650 | Default: `/*! For license information please see ${commentsFile} */`
|
651 |
|
652 | The banner text that points to the extracted file and will be added on top of the original file.
|
653 | 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.
|
654 | Will be wrapped into comment.
|
655 |
|
656 | **webpack.config.js**
|
657 |
|
658 | ```js
|
659 | module.exports = {
|
660 | optimization: {
|
661 | minimize: true,
|
662 | minimizer: [
|
663 | new TerserPlugin({
|
664 | extractComments: {
|
665 | condition: true,
|
666 | filename: (fileData) => {
|
667 | // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
|
668 | return `${fileData.filename}.LICENSE.txt${fileData.query}`;
|
669 | },
|
670 | banner: (commentsFile) => {
|
671 | return `My custom banner about license information ${commentsFile}`;
|
672 | },
|
673 | },
|
674 | }),
|
675 | ],
|
676 | },
|
677 | };
|
678 | ```
|
679 |
|
680 | ## Examples
|
681 |
|
682 | ### Preserve Comments
|
683 |
|
684 | Extract all legal comments (i.e. `/^\**!|@preserve|@license|@cc_on/i`) and preserve `/@license/i` comments.
|
685 |
|
686 | **webpack.config.js**
|
687 |
|
688 | ```js
|
689 | module.exports = {
|
690 | optimization: {
|
691 | minimize: true,
|
692 | minimizer: [
|
693 | new TerserPlugin({
|
694 | terserOptions: {
|
695 | format: {
|
696 | comments: /@license/i,
|
697 | },
|
698 | },
|
699 | extractComments: true,
|
700 | }),
|
701 | ],
|
702 | },
|
703 | };
|
704 | ```
|
705 |
|
706 | ### Remove Comments
|
707 |
|
708 | If you avoid building with comments, use this config:
|
709 |
|
710 | **webpack.config.js**
|
711 |
|
712 | ```js
|
713 | module.exports = {
|
714 | optimization: {
|
715 | minimize: true,
|
716 | minimizer: [
|
717 | new TerserPlugin({
|
718 | terserOptions: {
|
719 | format: {
|
720 | comments: false,
|
721 | },
|
722 | },
|
723 | extractComments: false,
|
724 | }),
|
725 | ],
|
726 | },
|
727 | };
|
728 | ```
|
729 |
|
730 | ### [`uglify-js`](https://github.com/mishoo/UglifyJS)
|
731 |
|
732 | [`UglifyJS`](https://github.com/mishoo/UglifyJS) is a JavaScript parser, minifier, compressor and beautifier toolkit.
|
733 |
|
734 | **webpack.config.js**
|
735 |
|
736 | ```js
|
737 | module.exports = {
|
738 | optimization: {
|
739 | minimize: true,
|
740 | minimizer: [
|
741 | new TerserPlugin({
|
742 | minify: TerserPlugin.uglifyJsMinify,
|
743 | // `terserOptions` options will be passed to `uglify-js`
|
744 | // Link to options - https://github.com/mishoo/UglifyJS#minify-options
|
745 | terserOptions: {},
|
746 | }),
|
747 | ],
|
748 | },
|
749 | };
|
750 | ```
|
751 |
|
752 | ### [`swc`](https://github.com/swc-project/swc)
|
753 |
|
754 | [`swc`](https://github.com/swc-project/swc) is a super-fast compiler written in rust; producing widely-supported javascript from modern standards and typescript.
|
755 |
|
756 | > ⚠ the `extractComments` option is not supported and all comments will be removed by default, it will be fixed in future
|
757 |
|
758 | **webpack.config.js**
|
759 |
|
760 | ```js
|
761 | module.exports = {
|
762 | optimization: {
|
763 | minimize: true,
|
764 | minimizer: [
|
765 | new TerserPlugin({
|
766 | minify: TerserPlugin.swcMinify,
|
767 | // `terserOptions` options will be passed to `swc` (`@swc/core`)
|
768 | // Link to options - https://swc.rs/docs/config-js-minify
|
769 | terserOptions: {},
|
770 | }),
|
771 | ],
|
772 | },
|
773 | };
|
774 | ```
|
775 |
|
776 | ### [`esbuild`](https://github.com/evanw/esbuild)
|
777 |
|
778 | [`esbuild`](https://github.com/evanw/esbuild) is an extremely fast JavaScript bundler and minifier.
|
779 |
|
780 | > ⚠ the `extractComments` option is not supported and all legal comments (i.e. copyright, licenses and etc) will be preserved
|
781 |
|
782 | **webpack.config.js**
|
783 |
|
784 | ```js
|
785 | module.exports = {
|
786 | optimization: {
|
787 | minimize: true,
|
788 | minimizer: [
|
789 | new TerserPlugin({
|
790 | minify: TerserPlugin.esbuildMinify,
|
791 | // `terserOptions` options will be passed to `esbuild`
|
792 | // Link to options - https://esbuild.github.io/api/#minify
|
793 | // 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:
|
794 | // terserOptions: {
|
795 | // minify: false,
|
796 | // minifyWhitespace: true,
|
797 | // minifyIdentifiers: false,
|
798 | // minifySyntax: true,
|
799 | // },
|
800 | terserOptions: {},
|
801 | }),
|
802 | ],
|
803 | },
|
804 | };
|
805 | ```
|
806 |
|
807 | ### Custom Minify Function
|
808 |
|
809 | Override default minify function - use `uglify-js` for minification.
|
810 |
|
811 | **webpack.config.js**
|
812 |
|
813 | ```js
|
814 | module.exports = {
|
815 | optimization: {
|
816 | minimize: true,
|
817 | minimizer: [
|
818 | new TerserPlugin({
|
819 | minify: (file, sourceMap) => {
|
820 | // https://github.com/mishoo/UglifyJS2#minify-options
|
821 | const uglifyJsOptions = {
|
822 | /* your `uglify-js` package options */
|
823 | };
|
824 |
|
825 | if (sourceMap) {
|
826 | uglifyJsOptions.sourceMap = {
|
827 | content: sourceMap,
|
828 | };
|
829 | }
|
830 |
|
831 | return require("uglify-js").minify(file, uglifyJsOptions);
|
832 | },
|
833 | }),
|
834 | ],
|
835 | },
|
836 | };
|
837 | ```
|
838 |
|
839 | ### Typescript
|
840 |
|
841 | With default terser minify function:
|
842 |
|
843 | ```ts
|
844 | module.exports = {
|
845 | optimization: {
|
846 | minimize: true,
|
847 | minimizer: [
|
848 | new TerserPlugin({
|
849 | terserOptions: {
|
850 | compress: true,
|
851 | },
|
852 | }),
|
853 | ],
|
854 | },
|
855 | };
|
856 | ```
|
857 |
|
858 | With built-in minify functions:
|
859 |
|
860 | ```ts
|
861 | import type { JsMinifyOptions as SwcOptions } from "@swc/core";
|
862 | import type { MinifyOptions as UglifyJSOptions } from "uglify-js";
|
863 | import type { TransformOptions as EsbuildOptions } from "esbuild";
|
864 | import type { MinifyOptions as TerserOptions } from "terser";
|
865 |
|
866 | module.exports = {
|
867 | optimization: {
|
868 | minimize: true,
|
869 | minimizer: [
|
870 | new TerserPlugin<SwcOptions>({
|
871 | minify: TerserPlugin.swcMinify,
|
872 | terserOptions: {
|
873 | // `swc` options
|
874 | },
|
875 | }),
|
876 | new TerserPlugin<UglifyJSOptions>({
|
877 | minify: TerserPlugin.uglifyJsMinify,
|
878 | terserOptions: {
|
879 | // `uglif-js` options
|
880 | },
|
881 | }),
|
882 | new TerserPlugin<EsbuildOptions>({
|
883 | minify: TerserPlugin.esbuildMinify,
|
884 | terserOptions: {
|
885 | // `esbuild` options
|
886 | },
|
887 | }),
|
888 |
|
889 | // Alternative usage:
|
890 | new TerserPlugin<TerserOptions>({
|
891 | minify: TerserPlugin.terserMinify,
|
892 | terserOptions: {
|
893 | // `terser` options
|
894 | },
|
895 | }),
|
896 | ],
|
897 | },
|
898 | };
|
899 | ```
|
900 |
|
901 | ## Contributing
|
902 |
|
903 | Please take a moment to read our contributing guidelines if you haven't yet done so.
|
904 |
|
905 | [CONTRIBUTING](./.github/CONTRIBUTING.md)
|
906 |
|
907 | ## License
|
908 |
|
909 | [MIT](./LICENSE)
|
910 |
|
911 | [npm]: https://img.shields.io/npm/v/terser-webpack-plugin.svg
|
912 | [npm-url]: https://npmjs.com/package/terser-webpack-plugin
|
913 | [node]: https://img.shields.io/node/v/terser-webpack-plugin.svg
|
914 | [node-url]: https://nodejs.org
|
915 | [tests]: https://github.com/webpack-contrib/terser-webpack-plugin/workflows/terser-webpack-plugin/badge.svg
|
916 | [tests-url]: https://github.com/webpack-contrib/terser-webpack-plugin/actions
|
917 | [cover]: https://codecov.io/gh/webpack-contrib/terser-webpack-plugin/branch/master/graph/badge.svg
|
918 | [cover-url]: https://codecov.io/gh/webpack-contrib/terser-webpack-plugin
|
919 | [chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg
|
920 | [chat-url]: https://gitter.im/webpack/webpack
|
921 | [size]: https://packagephobia.now.sh/badge?p=terser-webpack-plugin
|
922 | [size-url]: https://packagephobia.now.sh/result?p=terser-webpack-plugin
|