UNPKG

21.1 kBMarkdownView Raw
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
16This plugin uses [terser](https://github.com/terser/terser) to minify/minimize your JavaScript.
17
18## Getting Started
19
20Webpack 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
22To begin, you'll need to install `terser-webpack-plugin`:
23
24```console
25npm install terser-webpack-plugin --save-dev
26```
27
28or
29
30```console
31yarn add -D terser-webpack-plugin
32```
33
34or
35
36```console
37pnpm add -D terser-webpack-plugin
38```
39
40Then add the plugin to your `webpack` config. For example:
41
42**webpack.config.js**
43
44```js
45const TerserPlugin = require("terser-webpack-plugin");
46
47module.exports = {
48 optimization: {
49 minimize: true,
50 minimizer: [new TerserPlugin()],
51 },
52};
53```
54
55And 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
61Why?
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
66Using 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
80Type:
81
82```ts
83type test = string | RegExp | Array<string | RegExp>;
84```
85
86Default: `/\.m?js(\?.*)?$/i`
87
88Test to match files against.
89
90**webpack.config.js**
91
92```js
93module.exports = {
94 optimization: {
95 minimize: true,
96 minimizer: [
97 new TerserPlugin({
98 test: /\.js(\?.*)?$/i,
99 }),
100 ],
101 },
102};
103```
104
105### `include`
106
107Type:
108
109```ts
110type include = string | RegExp | Array<string | RegExp>;
111```
112
113Default: `undefined`
114
115Files to include.
116
117**webpack.config.js**
118
119```js
120module.exports = {
121 optimization: {
122 minimize: true,
123 minimizer: [
124 new TerserPlugin({
125 include: /\/includes/,
126 }),
127 ],
128 },
129};
130```
131
132### `exclude`
133
134Type:
135
136```ts
137type exclude = string | RegExp | Array<string | RegExp>;
138```
139
140Default: `undefined`
141
142Files to exclude.
143
144**webpack.config.js**
145
146```js
147module.exports = {
148 optimization: {
149 minimize: true,
150 minimizer: [
151 new TerserPlugin({
152 exclude: /\/excludes/,
153 }),
154 ],
155 },
156};
157```
158
159### `parallel`
160
161Type:
162
163```ts
164type parallel = boolean | number;
165```
166
167Default: `true`
168
169Use multi-process parallel running to improve the build speed.
170Default 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
178Enable/disable multi-process parallel running.
179
180**webpack.config.js**
181
182```js
183module.exports = {
184 optimization: {
185 minimize: true,
186 minimizer: [
187 new TerserPlugin({
188 parallel: true,
189 }),
190 ],
191 },
192};
193```
194
195#### `number`
196
197Enable multi-process parallel running and set number of concurrent runs.
198
199**webpack.config.js**
200
201```js
202module.exports = {
203 optimization: {
204 minimize: true,
205 minimizer: [
206 new TerserPlugin({
207 parallel: 4,
208 }),
209 ],
210 },
211};
212```
213
214### `minify`
215
216Type:
217
218```ts
219type 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
277Default: `TerserPlugin.terserMinify`
278
279Allows you to override default minify function.
280By default plugin uses [terser](https://github.com/terser/terser) package.
281Useful 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
289const 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`
306minify.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
319module.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
336Type:
337
338```ts
339type 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
359Default: [default](https://github.com/terser/terser#minify-options)
360
361Terser [options](https://github.com/terser/terser#minify-options).
362
363**webpack.config.js**
364
365```js
366module.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
395Type:
396
397```ts
398type 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
438Default: `true`
439
440Whether comments shall be extracted to a separate file, (see [details](https://github.com/webpack/webpack/commit/71933e979e51c533b432658d5e37917f9e71595a)).
441By default extract only comments using `/^\**!|@preserve|@license|@cc_on/i` regexp condition and remove remaining comments.
442If the original file is named `foo.js`, then the comments will be stored to `foo.js.LICENSE.txt`.
443The `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
447Enable/disable extracting comments.
448
449**webpack.config.js**
450
451```js
452module.exports = {
453 optimization: {
454 minimize: true,
455 minimizer: [
456 new TerserPlugin({
457 extractComments: true,
458 }),
459 ],
460 },
461};
462```
463
464#### `string`
465
466Extract `all` or `some` (use `/^\**!|@preserve|@license|@cc_on/i` RegExp) comments.
467
468**webpack.config.js**
469
470```js
471module.exports = {
472 optimization: {
473 minimize: true,
474 minimizer: [
475 new TerserPlugin({
476 extractComments: "all",
477 }),
478 ],
479 },
480};
481```
482
483#### `RegExp`
484
485All comments that match the given expression will be extracted to the separate file.
486
487**webpack.config.js**
488
489```js
490module.exports = {
491 optimization: {
492 minimize: true,
493 minimizer: [
494 new TerserPlugin({
495 extractComments: /@extract/i,
496 }),
497 ],
498 },
499};
500```
501
502#### `function`
503
504All comments that match the given expression will be extracted to the separate file.
505
506**webpack.config.js**
507
508```js
509module.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
529Allow to customize condition for extract comments, specify extracted file name and banner.
530
531**webpack.config.js**
532
533```js
534module.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
557Type:
558
559```ts
560type 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
578Condition what comments you need extract.
579
580**webpack.config.js**
581
582```js
583module.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
606Type:
607
608```ts
609type filename = string | ((fileData: any) => string) | undefined;
610```
611
612Default: `[file].LICENSE.txt[query]`
613
614Available placeholders: `[file]`, `[query]` and `[filebase]` (`[base]` for webpack 5).
615
616The file where the extracted comments will be stored.
617Default 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
624module.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
644Type:
645
646```ts
647type banner = string | boolean | ((commentsFile: string) => string) | undefined;
648```
649
650Default: `/*! For license information please see ${commentsFile} */`
651
652The banner text that points to the extracted file and will be added on top of the original file.
653Can be `false` (no banner), a `String`, or a `Function<(string) -> String>` that will be called with the filename where extracted comments have been stored.
654Will be wrapped into comment.
655
656**webpack.config.js**
657
658```js
659module.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
684Extract all legal comments (i.e. `/^\**!|@preserve|@license|@cc_on/i`) and preserve `/@license/i` comments.
685
686**webpack.config.js**
687
688```js
689module.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
708If you avoid building with comments, use this config:
709
710**webpack.config.js**
711
712```js
713module.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
737module.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
761module.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
785module.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
809Override default minify function - use `uglify-js` for minification.
810
811**webpack.config.js**
812
813```js
814module.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
841With default terser minify function:
842
843```ts
844module.exports = {
845 optimization: {
846 minimize: true,
847 minimizer: [
848 new TerserPlugin({
849 terserOptions: {
850 compress: true,
851 },
852 }),
853 ],
854 },
855};
856```
857
858With built-in minify functions:
859
860```ts
861import type { JsMinifyOptions as SwcOptions } from "@swc/core";
862import type { MinifyOptions as UglifyJSOptions } from "uglify-js";
863import type { TransformOptions as EsbuildOptions } from "esbuild";
864import type { MinifyOptions as TerserOptions } from "terser";
865
866module.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
903Please 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