UNPKG

13.5 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
21If you are using webpack v5 or above you do not need to install this plugin. Webpack v5 comes with the latest `terser-webpack-plugin` out of the box.
22
23To begin, you'll need to install `terser-webpack-plugin`:
24
25```console
26$ npm install terser-webpack-plugin --save-dev
27```
28
29Then add the plugin to your `webpack` config. For example:
30
31**webpack.config.js**
32
33```js
34const TerserPlugin = require("terser-webpack-plugin");
35
36module.exports = {
37 optimization: {
38 minimize: true,
39 minimizer: [new TerserPlugin()],
40 },
41};
42```
43
44And run `webpack` via your preferred method.
45
46## Note about source maps
47
48**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.**
49
50Why?
51
52- `eval` wraps modules in `eval("string")` and the minimizer does not handle strings.
53- `cheap` has not column information and minimizer generate only a single line, which leave only a single mapping.
54
55Using supported `devtool` values enable source map generation.
56
57## Options
58
59### `test`
60
61Type: `String|RegExp|Array<String|RegExp>`
62Default: `/\.m?js(\?.*)?$/i`
63
64Test to match files against.
65
66**webpack.config.js**
67
68```js
69module.exports = {
70 optimization: {
71 minimize: true,
72 minimizer: [
73 new TerserPlugin({
74 test: /\.js(\?.*)?$/i,
75 }),
76 ],
77 },
78};
79```
80
81### `include`
82
83Type: `String|RegExp|Array<String|RegExp>`
84Default: `undefined`
85
86Files to include.
87
88**webpack.config.js**
89
90```js
91module.exports = {
92 optimization: {
93 minimize: true,
94 minimizer: [
95 new TerserPlugin({
96 include: /\/includes/,
97 }),
98 ],
99 },
100};
101```
102
103### `exclude`
104
105Type: `String|RegExp|Array<String|RegExp>`
106Default: `undefined`
107
108Files to exclude.
109
110**webpack.config.js**
111
112```js
113module.exports = {
114 optimization: {
115 minimize: true,
116 minimizer: [
117 new TerserPlugin({
118 exclude: /\/excludes/,
119 }),
120 ],
121 },
122};
123```
124
125### `parallel`
126
127Type: `Boolean|Number`
128Default: `true`
129
130Use multi-process parallel running to improve the build speed.
131Default number of concurrent runs: `os.cpus().length - 1`.
132
133> ℹ️ Parallelization can speedup your build significantly and is therefore **highly recommended**.
134
135> ⚠️ 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)).
136
137#### `Boolean`
138
139Enable/disable multi-process parallel running.
140
141**webpack.config.js**
142
143```js
144module.exports = {
145 optimization: {
146 minimize: true,
147 minimizer: [
148 new TerserPlugin({
149 parallel: true,
150 }),
151 ],
152 },
153};
154```
155
156#### `Number`
157
158Enable multi-process parallel running and set number of concurrent runs.
159
160**webpack.config.js**
161
162```js
163module.exports = {
164 optimization: {
165 minimize: true,
166 minimizer: [
167 new TerserPlugin({
168 parallel: 4,
169 }),
170 ],
171 },
172};
173```
174
175### `minify`
176
177Type: `Function`
178Default: `undefined`
179
180Allows you to override default minify function.
181By default plugin uses [terser](https://github.com/terser-js/terser) package.
182Useful for using and testing unpublished versions or forks.
183
184> ⚠️ **Always use `require` inside `minify` function when `parallel` option enabled**.
185
186**webpack.config.js**
187
188```js
189module.exports = {
190 optimization: {
191 minimize: true,
192 minimizer: [
193 new TerserPlugin({
194 terserOptions: {
195 myCustomOption: true,
196 },
197 // Can be async
198 minify: (file, sourceMap, minimizerOptions) => {
199 // The `minimizerOptions` option contains option from the `terserOptions` option
200 // You can use `minimizerOptions.myCustomOption`
201 const extractedComments = [];
202
203 // Custom logic for extract comments
204
205 const { map, code } = require("uglify-module") // Or require('./path/to/uglify-module')
206 .minify(file, {
207 /* Your options for minification */
208 });
209
210 return { map, code, extractedComments };
211 },
212 }),
213 ],
214 },
215};
216```
217
218### `terserOptions`
219
220Type: `Object`
221Default: [default](https://github.com/terser-js/terser#minify-options)
222
223Terser minify [options](https://github.com/terser-js/terser#minify-options).
224
225**webpack.config.js**
226
227```js
228module.exports = {
229 optimization: {
230 minimize: true,
231 minimizer: [
232 new TerserPlugin({
233 terserOptions: {
234 ecma: undefined,
235 parse: {},
236 compress: {},
237 mangle: true, // Note `mangle.properties` is `false` by default.
238 module: false,
239 // Deprecated
240 output: null,
241 format: null,
242 toplevel: false,
243 nameCache: null,
244 ie8: false,
245 keep_classnames: undefined,
246 keep_fnames: false,
247 safari10: false,
248 },
249 }),
250 ],
251 },
252};
253```
254
255### `extractComments`
256
257Type: `Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>|Object`
258Default: `true`
259
260Whether comments shall be extracted to a separate file, (see [details](https://github.com/webpack/webpack/commit/71933e979e51c533b432658d5e37917f9e71595a)).
261By default extract only comments using `/^\**!|@preserve|@license|@cc_on/i` regexp condition and remove remaining comments.
262If the original file is named `foo.js`, then the comments will be stored to `foo.js.LICENSE.txt`.
263The `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.
264
265#### `Boolean`
266
267Enable/disable extracting comments.
268
269**webpack.config.js**
270
271```js
272module.exports = {
273 optimization: {
274 minimize: true,
275 minimizer: [
276 new TerserPlugin({
277 extractComments: true,
278 }),
279 ],
280 },
281};
282```
283
284#### `String`
285
286Extract `all` or `some` (use `/^\**!|@preserve|@license|@cc_on/i` RegExp) comments.
287
288**webpack.config.js**
289
290```js
291module.exports = {
292 optimization: {
293 minimize: true,
294 minimizer: [
295 new TerserPlugin({
296 extractComments: "all",
297 }),
298 ],
299 },
300};
301```
302
303#### `RegExp`
304
305All comments that match the given expression will be extracted to the separate file.
306
307**webpack.config.js**
308
309```js
310module.exports = {
311 optimization: {
312 minimize: true,
313 minimizer: [
314 new TerserPlugin({
315 extractComments: /@extract/i,
316 }),
317 ],
318 },
319};
320```
321
322#### `Function<(node, comment) -> Boolean>`
323
324All comments that match the given expression will be extracted to the separate file.
325
326**webpack.config.js**
327
328```js
329module.exports = {
330 optimization: {
331 minimize: true,
332 minimizer: [
333 new TerserPlugin({
334 extractComments: (astNode, comment) => {
335 if (/@extract/i.test(comment.value)) {
336 return true;
337 }
338
339 return false;
340 },
341 }),
342 ],
343 },
344};
345```
346
347#### `Object`
348
349Allow to customize condition for extract comments, specify extracted file name and banner.
350
351**webpack.config.js**
352
353```js
354module.exports = {
355 optimization: {
356 minimize: true,
357 minimizer: [
358 new TerserPlugin({
359 extractComments: {
360 condition: /^\**!|@preserve|@license|@cc_on/i,
361 filename: (fileData) => {
362 // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
363 return `${fileData.filename}.LICENSE.txt${fileData.query}`;
364 },
365 banner: (licenseFile) => {
366 return `License information can be found in ${licenseFile}`;
367 },
368 },
369 }),
370 ],
371 },
372};
373```
374
375##### `condition`
376
377Type: `Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>`
378
379Condition what comments you need extract.
380
381**webpack.config.js**
382
383```js
384module.exports = {
385 optimization: {
386 minimize: true,
387 minimizer: [
388 new TerserPlugin({
389 extractComments: {
390 condition: "some",
391 filename: (fileData) => {
392 // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
393 return `${fileData.filename}.LICENSE.txt${fileData.query}`;
394 },
395 banner: (licenseFile) => {
396 return `License information can be found in ${licenseFile}`;
397 },
398 },
399 }),
400 ],
401 },
402};
403```
404
405##### `filename`
406
407Type: `String|Function<(string) -> String>`
408Default: `[file].LICENSE.txt[query]`
409
410Available placeholders: `[file]`, `[query]` and `[filebase]` (`[base]` for webpack 5).
411
412The file where the extracted comments will be stored.
413Default is to append the suffix `.LICENSE.txt` to the original filename.
414
415> ⚠️ We highly recommend using the `txt` extension. Using `js`/`cjs`/`mjs` extensions may conflict with existing assets which leads to broken code.
416
417**webpack.config.js**
418
419```js
420module.exports = {
421 optimization: {
422 minimize: true,
423 minimizer: [
424 new TerserPlugin({
425 extractComments: {
426 condition: /^\**!|@preserve|@license|@cc_on/i,
427 filename: "extracted-comments.js",
428 banner: (licenseFile) => {
429 return `License information can be found in ${licenseFile}`;
430 },
431 },
432 }),
433 ],
434 },
435};
436```
437
438##### `banner`
439
440Type: `Boolean|String|Function<(string) -> String>`
441Default: `/*! For license information please see ${commentsFile} */`
442
443The banner text that points to the extracted file and will be added on top of the original file.
444Can be `false` (no banner), a `String`, or a `Function<(string) -> String>` that will be called with the filename where extracted comments have been stored.
445Will be wrapped into comment.
446
447**webpack.config.js**
448
449```js
450module.exports = {
451 optimization: {
452 minimize: true,
453 minimizer: [
454 new TerserPlugin({
455 extractComments: {
456 condition: true,
457 filename: (fileData) => {
458 // The "fileData" argument contains object with "filename", "basename", "query" and "hash"
459 return `${fileData.filename}.LICENSE.txt${fileData.query}`;
460 },
461 banner: (commentsFile) => {
462 return `My custom banner about license information ${commentsFile}`;
463 },
464 },
465 }),
466 ],
467 },
468};
469```
470
471## Examples
472
473### Preserve Comments
474
475Extract all legal comments (i.e. `/^\**!|@preserve|@license|@cc_on/i`) and preserve `/@license/i` comments.
476
477**webpack.config.js**
478
479```js
480module.exports = {
481 optimization: {
482 minimize: true,
483 minimizer: [
484 new TerserPlugin({
485 terserOptions: {
486 format: {
487 comments: /@license/i,
488 },
489 },
490 extractComments: true,
491 }),
492 ],
493 },
494};
495```
496
497### Remove Comments
498
499If you avoid building with comments, use this config:
500
501**webpack.config.js**
502
503```js
504module.exports = {
505 optimization: {
506 minimize: true,
507 minimizer: [
508 new TerserPlugin({
509 terserOptions: {
510 format: {
511 comments: false,
512 },
513 },
514 extractComments: false,
515 }),
516 ],
517 },
518};
519```
520
521### Custom Minify Function
522
523Override default minify function - use `uglify-js` for minification.
524
525**webpack.config.js**
526
527```js
528module.exports = {
529 optimization: {
530 minimize: true,
531 minimizer: [
532 new TerserPlugin({
533 minify: (file, sourceMap) => {
534 // https://github.com/mishoo/UglifyJS2#minify-options
535 const uglifyJsOptions = {
536 /* your `uglify-js` package options */
537 };
538
539 if (sourceMap) {
540 uglifyJsOptions.sourceMap = {
541 content: sourceMap,
542 };
543 }
544
545 return require("uglify-js").minify(file, uglifyJsOptions);
546 },
547 }),
548 ],
549 },
550};
551```
552
553## Contributing
554
555Please take a moment to read our contributing guidelines if you haven't yet done so.
556
557[CONTRIBUTING](./.github/CONTRIBUTING.md)
558
559## License
560
561[MIT](./LICENSE)
562
563[npm]: https://img.shields.io/npm/v/terser-webpack-plugin.svg
564[npm-url]: https://npmjs.com/package/terser-webpack-plugin
565[node]: https://img.shields.io/node/v/terser-webpack-plugin.svg
566[node-url]: https://nodejs.org
567[deps]: https://david-dm.org/webpack-contrib/terser-webpack-plugin.svg
568[deps-url]: https://david-dm.org/webpack-contrib/terser-webpack-plugin
569[tests]: https://github.com/webpack-contrib/terser-webpack-plugin/workflows/terser-webpack-plugin/badge.svg
570[tests-url]: https://github.com/webpack-contrib/terser-webpack-plugin/actions
571[cover]: https://codecov.io/gh/webpack-contrib/terser-webpack-plugin/branch/master/graph/badge.svg
572[cover-url]: https://codecov.io/gh/webpack-contrib/terser-webpack-plugin
573[chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg
574[chat-url]: https://gitter.im/webpack/webpack
575[size]: https://packagephobia.now.sh/badge?p=terser-webpack-plugin
576[size-url]: https://packagephobia.now.sh/result?p=terser-webpack-plugin