UNPKG

17.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[![deps][deps]][deps-url]
10[![tests][tests]][tests-url]
11[![cover][cover]][cover-url]
12[![chat][chat]][chat-url]
13[![size][size]][size-url]
14
15# terser-webpack-plugin
16
17This plugin uses [terser](https://github.com/terser-js/terser) to minify your JavaScript.
18
19## Getting Started
20
21To begin, you'll need to install `terser-webpack-plugin`:
22
23```console
24$ npm install terser-webpack-plugin --save-dev
25```
26
27Then add the plugin to your `webpack` config. For example:
28
29**webpack.config.js**
30
31```js
32const TerserPlugin = require('terser-webpack-plugin');
33
34module.exports = {
35 optimization: {
36 minimize: true,
37 minimizer: [new TerserPlugin()],
38 },
39};
40```
41
42And run `webpack` via your preferred method.
43
44## Options
45
46### `test`
47
48Type: `String|RegExp|Array<String|RegExp>`
49Default: `/\.m?js(\?.*)?$/i`
50
51Test to match files against.
52
53**webpack.config.js**
54
55```js
56module.exports = {
57 optimization: {
58 minimize: true,
59 minimizer: [
60 new TerserPlugin({
61 test: /\.js(\?.*)?$/i,
62 }),
63 ],
64 },
65};
66```
67
68### `include`
69
70Type: `String|RegExp|Array<String|RegExp>`
71Default: `undefined`
72
73Files to include.
74
75**webpack.config.js**
76
77```js
78module.exports = {
79 optimization: {
80 minimize: true,
81 minimizer: [
82 new TerserPlugin({
83 include: /\/includes/,
84 }),
85 ],
86 },
87};
88```
89
90### `exclude`
91
92Type: `String|RegExp|Array<String|RegExp>`
93Default: `undefined`
94
95Files to exclude.
96
97**webpack.config.js**
98
99```js
100module.exports = {
101 optimization: {
102 minimize: true,
103 minimizer: [
104 new TerserPlugin({
105 exclude: /\/excludes/,
106 }),
107 ],
108 },
109};
110```
111
112### `chunkFilter`
113
114Type: `Function<(chunk) -> boolean>`
115Default: `() => true`
116
117Allowing to filter which chunks should be uglified (by default all chunks are uglified).
118Return `true` to uglify the chunk, `false` otherwise.
119
120**webpack.config.js**
121
122```js
123module.exports = {
124 optimization: {
125 minimize: true,
126 minimizer: [
127 new TerserPlugin({
128 chunkFilter: (chunk) => {
129 // Exclude uglification for the `vendor` chunk
130 if (chunk.name === 'vendor') {
131 return false;
132 }
133
134 return true;
135 },
136 }),
137 ],
138 },
139};
140```
141
142### `cache`
143
144Type: `Boolean|String`
145Default: `true`
146
147Enable file caching.
148Default path to cache directory: `node_modules/.cache/terser-webpack-plugin`.
149
150> ℹ️ If you use your own `minify` function please read the `minify` section for cache invalidation correctly.
151
152#### `Boolean`
153
154Enable/disable file caching.
155
156**webpack.config.js**
157
158```js
159module.exports = {
160 optimization: {
161 minimize: true,
162 minimizer: [
163 new TerserPlugin({
164 cache: true,
165 }),
166 ],
167 },
168};
169```
170
171#### `String`
172
173Enable file caching and set path to cache directory.
174
175**webpack.config.js**
176
177```js
178module.exports = {
179 optimization: {
180 minimize: true,
181 minimizer: [
182 new TerserPlugin({
183 cache: 'path/to/cache',
184 }),
185 ],
186 },
187};
188```
189
190### `cacheKeys`
191
192Type: `Function<(defaultCacheKeys, file) -> Object>`
193Default: `defaultCacheKeys => defaultCacheKeys`
194
195Allows you to override default cache keys.
196
197Default cache keys:
198
199```js
200({
201 terser: require('terser/package.json').version, // terser version
202 'terser-webpack-plugin': require('../package.json').version, // plugin version
203 'terser-webpack-plugin-options': this.options, // plugin options
204 path: compiler.outputPath ? `${compiler.outputPath}/${file}` : file, // asset path
205 hash: crypto
206 .createHash('md4')
207 .update(input)
208 .digest('hex'), // source file hash
209});
210```
211
212**webpack.config.js**
213
214```js
215module.exports = {
216 optimization: {
217 minimize: true,
218 minimizer: [
219 new TerserPlugin({
220 cache: true,
221 cacheKeys: (defaultCacheKeys, file) => {
222 defaultCacheKeys.myCacheKey = 'myCacheKeyValue';
223
224 return defaultCacheKeys;
225 },
226 }),
227 ],
228 },
229};
230```
231
232### `parallel`
233
234Type: `Boolean|Number`
235Default: `true`
236
237Use multi-process parallel running to improve the build speed.
238Default number of concurrent runs: `os.cpus().length - 1`.
239
240> ℹ️ Parallelization can speedup your build significantly and is therefore **highly recommended**.
241
242#### `Boolean`
243
244Enable/disable multi-process parallel running.
245
246**webpack.config.js**
247
248```js
249module.exports = {
250 optimization: {
251 minimize: true,
252 minimizer: [
253 new TerserPlugin({
254 parallel: true,
255 }),
256 ],
257 },
258};
259```
260
261#### `Number`
262
263Enable multi-process parallel running and set number of concurrent runs.
264
265**webpack.config.js**
266
267```js
268module.exports = {
269 optimization: {
270 minimize: true,
271 minimizer: [
272 new TerserPlugin({
273 parallel: 4,
274 }),
275 ],
276 },
277};
278```
279
280### `sourceMap`
281
282Type: `Boolean`
283Default: `false` (see below for details around `devtool` value and `SourceMapDevToolPlugin` plugin)
284
285**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.**
286
287Why?
288
289- `eval` wraps modules in `eval("string")` and the minimizer does not handle strings.
290- `cheap` has not column information and minimizer generate only a single line, which leave only a single mapping.
291
292The plugin respect the [`devtool`](https://webpack.js.org/configuration/devtool/) and using the `SourceMapDevToolPlugin` plugin.
293Using supported `devtool` values enable source map generation.
294Using `SourceMapDevToolPlugin` with enabled the `columns` option enables source map generation.
295
296Use source maps to map error message locations to modules (this slows down the compilation).
297If you use your own `minify` function please read the `minify` section for handling source maps correctly.
298
299**webpack.config.js**
300
301```js
302module.exports = {
303 optimization: {
304 minimize: true,
305 minimizer: [
306 new TerserPlugin({
307 sourceMap: true,
308 }),
309 ],
310 },
311};
312```
313
314### `minify`
315
316Type: `Function`
317Default: `undefined`
318
319Allows you to override default minify function.
320By default plugin uses [terser](https://github.com/terser-js/terser) package.
321Useful for using and testing unpublished versions or forks.
322
323> ⚠️ **Always use `require` inside `minify` function when `parallel` option enabled**.
324
325**webpack.config.js**
326
327```js
328module.exports = {
329 optimization: {
330 minimize: true,
331 minimizer: [
332 new TerserPlugin({
333 minify: (file, sourceMap) => {
334 const extractedComments = [];
335
336 // Custom logic for extract comments
337
338 const { error, map, code, warnings } = require('uglify-module') // Or require('./path/to/uglify-module')
339 .minify(file, {
340 /* Your options for minification */
341 });
342
343 return { error, map, code, warnings, extractedComments };
344 },
345 }),
346 ],
347 },
348};
349```
350
351### `terserOptions`
352
353Type: `Object`
354Default: [default](https://github.com/terser-js/terser#minify-options)
355
356Terser minify [options](https://github.com/terser-js/terser#minify-options).
357
358**webpack.config.js**
359
360```js
361module.exports = {
362 optimization: {
363 minimize: true,
364 minimizer: [
365 new TerserPlugin({
366 terserOptions: {
367 ecma: undefined,
368 warnings: false,
369 parse: {},
370 compress: {},
371 mangle: true, // Note `mangle.properties` is `false` by default.
372 module: false,
373 output: null,
374 toplevel: false,
375 nameCache: null,
376 ie8: false,
377 keep_classnames: undefined,
378 keep_fnames: false,
379 safari10: false,
380 },
381 }),
382 ],
383 },
384};
385```
386
387### `extractComments`
388
389Type: `Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>|Object`
390Default: `true`
391
392Whether comments shall be extracted to a separate file, (see [details](https://github.com/webpack/webpack/commit/71933e979e51c533b432658d5e37917f9e71595a)).
393By default extract only comments using `/^\**!|@preserve|@license|@cc_on/i` regexp condition and remove remaining comments.
394If the original file is named `foo.js`, then the comments will be stored to `foo.js.LICENSE`.
395The `terserOptions.output.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.
396
397#### `Boolean`
398
399Enable/disable extracting comments.
400
401**webpack.config.js**
402
403```js
404module.exports = {
405 optimization: {
406 minimize: true,
407 minimizer: [
408 new TerserPlugin({
409 extractComments: true,
410 }),
411 ],
412 },
413};
414```
415
416#### `String`
417
418Extract `all` or `some` (use `/^\**!|@preserve|@license|@cc_on/i` RegExp) comments.
419
420**webpack.config.js**
421
422```js
423module.exports = {
424 optimization: {
425 minimize: true,
426 minimizer: [
427 new TerserPlugin({
428 extractComments: 'all',
429 }),
430 ],
431 },
432};
433```
434
435#### `RegExp`
436
437All comments that match the given expression will be extracted to the separate file.
438
439**webpack.config.js**
440
441```js
442module.exports = {
443 optimization: {
444 minimize: true,
445 minimizer: [
446 new TerserPlugin({
447 extractComments: /@extract/i,
448 }),
449 ],
450 },
451};
452```
453
454#### `Function<(node, comment) -> Boolean>`
455
456All comments that match the given expression will be extracted to the separate file.
457
458**webpack.config.js**
459
460```js
461module.exports = {
462 optimization: {
463 minimize: true,
464 minimizer: [
465 new TerserPlugin({
466 extractComments: (astNode, comment) => {
467 if (/@extract/i.test(comment.value)) {
468 return true;
469 }
470
471 return false;
472 },
473 }),
474 ],
475 },
476};
477```
478
479#### `Object`
480
481Allow to customize condition for extract comments, specify extracted file name and banner.
482
483**webpack.config.js**
484
485```js
486module.exports = {
487 optimization: {
488 minimize: true,
489 minimizer: [
490 new TerserPlugin({
491 extractComments: {
492 condition: /^\**!|@preserve|@license|@cc_on/i,
493 filename: (file, fileData) => {
494 // A file can contain a query string (for example when you have `output.filename: '[name].js?[chunkhash]'`)
495 // You must consider this
496 // The "fileData" argument contains object with "filename", "basename", "query"
497 return file.replace(/\.(\w+)($|\?)/, '.$1.LICENSE$2');
498 },
499 banner: (licenseFile) => {
500 return `License information can be found in ${licenseFile}`;
501 },
502 },
503 }),
504 ],
505 },
506};
507```
508
509##### `condition`
510
511Type: `Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>`
512
513Condition what comments you need extract.
514
515**webpack.config.js**
516
517```js
518module.exports = {
519 optimization: {
520 minimize: true,
521 minimizer: [
522 new TerserPlugin({
523 extractComments: {
524 condition: 'some',
525 filename: (file, fileData) => {
526 // A file can contain a query string (for example when you have `output.filename: '[name].js?[chunkhash]'`)
527 // You must consider this
528 return file.replace(/\.(\w+)($|\?)/, '.$1.LICENSE$2');
529 },
530 banner: (licenseFile) => {
531 return `License information can be found in ${licenseFile}`;
532 },
533 },
534 }),
535 ],
536 },
537};
538```
539
540##### `filename`
541
542Type: `String|Function<(string) -> String>`
543Default: `[file].LICENSE[query]`
544
545Available placeholders: `[file]`, `[query]` and `[filebase]`.
546
547The file where the extracted comments will be stored.
548Default is to append the suffix `.LICENSE` to the original filename.
549
550**webpack.config.js**
551
552```js
553module.exports = {
554 optimization: {
555 minimize: true,
556 minimizer: [
557 new TerserPlugin({
558 extractComments: {
559 condition: /^\**!|@preserve|@license|@cc_on/i,
560 filename: 'extracted-comments.js',
561 banner: (licenseFile) => {
562 return `License information can be found in ${licenseFile}`;
563 },
564 },
565 }),
566 ],
567 },
568};
569```
570
571##### `banner`
572
573Type: `Boolean|String|Function<(string) -> String>`
574Default: `/*! For license information please see ${commentsFile} */`
575
576The banner text that points to the extracted file and will be added on top of the original file.
577Can be `false` (no banner), a `String`, or a `Function<(string) -> String>` that will be called with the filename where extracted comments have been stored.
578Will be wrapped into comment.
579
580**webpack.config.js**
581
582```js
583module.exports = {
584 optimization: {
585 minimize: true,
586 minimizer: [
587 new TerserPlugin({
588 extractComments: {
589 condition: true,
590 filename: (file, fileData) => {
591 // A file can contain a query string (for example when you have `output.filename: '[name].js?[chunkhash]'`)
592 // You must consider this
593 return file.replace(/\.(\w+)($|\?)/, '.$1.LICENSE$2');
594 },
595 banner: (commentsFile) => {
596 return `My custom banner about license information ${commentsFile}`;
597 },
598 },
599 }),
600 ],
601 },
602};
603```
604
605### `warningsFilter`
606
607Type: `Function<(warning, source, file) -> Boolean>`
608Default: `() => true`
609
610Allow to filter [terser](https://github.com/terser-js/terser) warnings.
611Return `true` to keep the warning, a falsy value (`false`/`null`/`undefined`) otherwise.
612
613> ⚠️ The `source` argument will contain `undefined` if you don't use source maps.
614
615**webpack.config.js**
616
617```js
618module.exports = {
619 optimization: {
620 minimize: true,
621 minimizer: [
622 new TerserPlugin({
623 warningsFilter: (warning, source, file) => {
624 if (/Dropping unreachable code/i.test(warning)) {
625 return true;
626 }
627
628 if (/source\.js/i.test(source)) {
629 return true;
630 }
631
632 if (/file\.js/i.test(file)) {
633 return true;
634 }
635
636 return false;
637 },
638 }),
639 ],
640 },
641};
642```
643
644## Examples
645
646### Preserve Comments
647
648Extract all legal comments (i.e. `/^\**!|@preserve|@license|@cc_on/i`) and preserve `/@license/i` comments.
649
650**webpack.config.js**
651
652```js
653module.exports = {
654 optimization: {
655 minimize: true,
656 minimizer: [
657 new TerserPlugin({
658 terserOptions: {
659 output: {
660 comments: /@license/i,
661 },
662 },
663 extractComments: true,
664 }),
665 ],
666 },
667};
668```
669
670### Remove Comments
671
672If you avoid building with comments, use this config:
673
674**webpack.config.js**
675
676```js
677module.exports = {
678 optimization: {
679 minimize: true,
680 minimizer: [
681 new TerserPlugin({
682 terserOptions: {
683 output: {
684 comments: false,
685 },
686 },
687 extractComments: false,
688 }),
689 ],
690 },
691};
692```
693
694### Custom Minify Function
695
696Override default minify function - use `uglify-js` for minification.
697
698**webpack.config.js**
699
700```js
701module.exports = {
702 optimization: {
703 minimize: true,
704 minimizer: [
705 new TerserPlugin({
706 // Uncomment lines below for cache invalidation correctly
707 // cache: true,
708 // cacheKeys: (defaultCacheKeys) => {
709 // delete defaultCacheKeys.terser;
710 //
711 // return Object.assign(
712 // {},
713 // defaultCacheKeys,
714 // { 'uglify-js': require('uglify-js/package.json').version },
715 // );
716 // },
717 minify: (file, sourceMap) => {
718 // https://github.com/mishoo/UglifyJS2#minify-options
719 const uglifyJsOptions = {
720 /* your `uglify-js` package options */
721 };
722
723 if (sourceMap) {
724 uglifyJsOptions.sourceMap = {
725 content: sourceMap,
726 };
727 }
728
729 return require('uglify-js').minify(file, uglifyJsOptions);
730 },
731 }),
732 ],
733 },
734};
735```
736
737## Contributing
738
739Please take a moment to read our contributing guidelines if you haven't yet done so.
740
741[CONTRIBUTING](./.github/CONTRIBUTING.md)
742
743## License
744
745[MIT](./LICENSE)
746
747[npm]: https://img.shields.io/npm/v/terser-webpack-plugin.svg
748[npm-url]: https://npmjs.com/package/terser-webpack-plugin
749[node]: https://img.shields.io/node/v/terser-webpack-plugin.svg
750[node-url]: https://nodejs.org
751[deps]: https://david-dm.org/webpack-contrib/terser-webpack-plugin.svg
752[deps-url]: https://david-dm.org/webpack-contrib/terser-webpack-plugin
753[tests]: https://dev.azure.com/webpack-contrib/terser-webpack-plugin/_apis/build/status/webpack-contrib.terser-webpack-plugin?branchName=master
754[tests-url]: https://dev.azure.com/webpack-contrib/terser-webpack-plugin/_build/latest?definitionId=7&branchName=master
755[cover]: https://codecov.io/gh/webpack-contrib/terser-webpack-plugin/branch/master/graph/badge.svg
756[cover-url]: https://codecov.io/gh/webpack-contrib/terser-webpack-plugin
757[chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg
758[chat-url]: https://gitter.im/webpack/webpack
759[size]: https://packagephobia.now.sh/badge?p=terser-webpack-plugin
760[size-url]: https://packagephobia.now.sh/result?p=terser-webpack-plugin