UNPKG

52.5 kBMarkdownView Raw
1terser
2======
3
4![Terser](https://raw.githubusercontent.com/terser-js/terser/master/logo.png)
5
6A JavaScript parser and mangler/compressor toolkit for ES6+.
7
8*note*: You can support this project on patreon: <a target="_blank" rel="nofollow" href="https://www.patreon.com/terser_jscomp_maintainer"><img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" alt="patron" width="100px" height="auto"></a>. Check out PATRONS.md for our first-tier patrons.
9
10Terser recommends you use RollupJS to bundle your modules, as that produces smaller code overall.
11
12*Beautification* has been undocumented and is *being removed* from terser, we recommend you use [prettier](https://npmjs.com/package/prettier).
13
14[![Build Status](https://travis-ci.org/terser-js/terser.svg?branch=master)](https://travis-ci.org/terser-js/terser) [![Coverage Status](https://coveralls.io/repos/github/terser-js/terser/badge.svg?branch=master)](https://coveralls.io/github/terser-js/terser?branch=master)
15
16
17Why choose terser?
18------------------
19
20`uglify-es` is [no longer maintained](https://github.com/mishoo/UglifyJS2/issues/3156#issuecomment-392943058) and `uglify-js` does not support ES6+.
21
22**`terser`** is a fork of `uglify-es` that retains API and CLI compatibility
23with `uglify-es` and `uglify-js@3`.
24
25Install
26-------
27
28First make sure you have installed the latest version of [node.js](http://nodejs.org/)
29(You may need to restart your computer after this step).
30
31From NPM for use as a command line app:
32
33 npm install terser -g
34
35From NPM for programmatic use:
36
37 npm install terser
38
39# Command line usage
40
41 terser [input files] [options]
42
43Terser can take multiple input files. It's recommended that you pass the
44input files first, then pass the options. Terser will parse input files
45in sequence and apply any compression options. The files are parsed in the
46same global scope, that is, a reference from a file to some
47variable/function declared in another file will be matched properly.
48
49If no input file is specified, Terser will read from STDIN.
50
51If you wish to pass your options before the input files, separate the two with
52a double dash to prevent input files being used as option arguments:
53
54 terser --compress --mangle -- input.js
55
56### Command line options
57
58```
59 -h, --help Print usage information.
60 `--help options` for details on available options.
61 -V, --version Print version number.
62 -p, --parse <options> Specify parser options:
63 `acorn` Use Acorn for parsing.
64 `bare_returns` Allow return outside of functions.
65 Useful when minifying CommonJS
66 modules and Userscripts that may
67 be anonymous function wrapped (IIFE)
68 by the .user.js engine `caller`.
69 `expression` Parse a single expression, rather than
70 a program (for parsing JSON).
71 `spidermonkey` Assume input files are SpiderMonkey
72 AST format (as JSON).
73 -c, --compress [options] Enable compressor/specify compressor options:
74 `pure_funcs` List of functions that can be safely
75 removed when their return values are
76 not used.
77 -m, --mangle [options] Mangle names/specify mangler options:
78 `reserved` List of names that should not be mangled.
79 --mangle-props [options] Mangle properties/specify mangler options:
80 `builtins` Mangle property names that overlaps
81 with standard JavaScript globals.
82 `debug` Add debug prefix and suffix.
83 `domprops` Mangle property names that overlaps
84 with DOM properties.
85 `keep_quoted` Only mangle unquoted properties.
86 `regex` Only mangle matched property names.
87 `reserved` List of names that should not be mangled.
88 `preamble` Preamble to prepend to the output. You
89 can use this to insert a comment, for
90 example for licensing information.
91 This will not be parsed, but the source
92 map will adjust for its presence.
93 `quote_style` Quote style:
94 0 - auto
95 1 - single
96 2 - double
97 3 - original
98 `wrap_iife` Wrap IIFEs in parenthesis. Note: you may
99 want to disable `negate_iife` under
100 compressor options.
101 -o, --output <file> Output file path (default STDOUT). Specify `ast` or
102 `spidermonkey` to write Terser or SpiderMonkey AST
103 as JSON to STDOUT respectively.
104 --comments [filter] Preserve copyright comments in the output. By
105 default this works like Google Closure, keeping
106 JSDoc-style comments that contain "@license" or
107 "@preserve". You can optionally pass one of the
108 following arguments to this flag:
109 - "all" to keep all comments
110 - a valid JS RegExp like `/foo/` or `/^!/` to
111 keep only matching comments.
112 Note that currently not *all* comments can be
113 kept when compression is on, because of dead
114 code removal or cascading statements into
115 sequences.
116 --config-file <file> Read `minify()` options from JSON file.
117 -d, --define <expr>[=value] Global definitions.
118 --ecma <version> Specify ECMAScript release: 5, 6, 7 or 8.
119 -e, --enclose [arg[:value]] Embed output in a big function with configurable
120 arguments and values.
121 --ie8 Support non-standard Internet Explorer 8.
122 Equivalent to setting `ie8: true` in `minify()`
123 for `compress`, `mangle` and `output` options.
124 By default Terser will not try to be IE-proof.
125 --keep-classnames Do not mangle/drop class names.
126 --keep-fnames Do not mangle/drop function names. Useful for
127 code relying on Function.prototype.name.
128 --module Input is an ES6 module. If `compress` or `mangle` is
129 enabled then the `toplevel` option will be enabled.
130 --name-cache <file> File to hold mangled name mappings.
131 --safari10 Support non-standard Safari 10/11.
132 Equivalent to setting `safari10: true` in `minify()`
133 for `mangle` and `output` options.
134 By default `terser` will not work around
135 Safari 10/11 bugs.
136 --source-map [options] Enable source map/specify source map options:
137 `base` Path to compute relative paths from input files.
138 `content` Input source map, useful if you're compressing
139 JS that was generated from some other original
140 code. Specify "inline" if the source map is
141 included within the sources.
142 `filename` Name and/or location of the output source.
143 `includeSources` Pass this flag if you want to include
144 the content of source files in the
145 source map as sourcesContent property.
146 `root` Path to the original source to be included in
147 the source map.
148 `url` If specified, path to the source map to append in
149 `//# sourceMappingURL`.
150 --timings Display operations run time on STDERR.
151 --toplevel Compress and/or mangle variables in top level scope.
152 --verbose Print diagnostic messages.
153 --warn Print warning messages.
154 --wrap <name> Embed everything in a big function, making the
155 “exports” and “global” variables available. You
156 need to pass an argument to this option to
157 specify the name that your module will take
158 when included in, say, a browser.
159```
160
161Specify `--output` (`-o`) to declare the output file. Otherwise the output
162goes to STDOUT.
163
164## CLI source map options
165
166Terser can generate a source map file, which is highly useful for
167debugging your compressed JavaScript. To get a source map, pass
168`--source-map --output output.js` (source map will be written out to
169`output.js.map`).
170
171Additional options:
172
173- `--source-map "filename='<NAME>'"` to specify the name of the source map.
174
175- `--source-map "root='<URL>'"` to pass the URL where the original files can be found.
176
177- `--source-map "url='<URL>'"` to specify the URL where the source map can be found.
178 Otherwise Terser assumes HTTP `X-SourceMap` is being used and will omit the
179 `//# sourceMappingURL=` directive.
180
181For example:
182
183 terser js/file1.js js/file2.js \
184 -o foo.min.js -c -m \
185 --source-map "root='http://foo.com/src',url='foo.min.js.map'"
186
187The above will compress and mangle `file1.js` and `file2.js`, will drop the
188output in `foo.min.js` and the source map in `foo.min.js.map`. The source
189mapping will refer to `http://foo.com/src/js/file1.js` and
190`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src`
191as the source map root, and the original files as `js/file1.js` and
192`js/file2.js`).
193
194### Composed source map
195
196When you're compressing JS code that was output by a compiler such as
197CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd
198like to map back to the original code (i.e. CoffeeScript). Terser has an
199option to take an input source map. Assuming you have a mapping from
200CoffeeScript → compiled JS, Terser can generate a map from CoffeeScript →
201compressed JS by mapping every token in the compiled JS to its original
202location.
203
204To use this feature pass `--source-map "content='/path/to/input/source.map'"`
205or `--source-map "content=inline"` if the source map is included inline with
206the sources.
207
208## CLI compress options
209
210You need to pass `--compress` (`-c`) to enable the compressor. Optionally
211you can pass a comma-separated list of [compress options](#compress-options).
212
213Options are in the form `foo=bar`, or just `foo` (the latter implies
214a boolean option that you want to set `true`; it's effectively a
215shortcut for `foo=true`).
216
217Example:
218
219 terser file.js -c toplevel,sequences=false
220
221## CLI mangle options
222
223To enable the mangler you need to pass `--mangle` (`-m`). The following
224(comma-separated) options are supported:
225
226- `toplevel` (default `false`) -- mangle names declared in the top level scope.
227
228- `eval` (default `false`) -- mangle names visible in scopes where `eval` or `with` are used.
229
230When mangling is enabled but you want to prevent certain names from being
231mangled, you can declare those names with `--mangle reserved` — pass a
232comma-separated list of names. For example:
233
234 terser ... -m reserved=['$','require','exports']
235
236to prevent the `require`, `exports` and `$` names from being changed.
237
238### CLI mangling property names (`--mangle-props`)
239
240**Note:** THIS *MIGHT* BREAK YOUR CODE. Mangling property names
241is a separate step, different from variable name mangling. Pass
242`--mangle-props` to enable it. It will mangle all properties in the
243input code with the exception of built in DOM properties and properties
244in core JavaScript classes. For example:
245
246```javascript
247// example.js
248var x = {
249 baz_: 0,
250 foo_: 1,
251 calc: function() {
252 return this.foo_ + this.baz_;
253 }
254};
255x.bar_ = 2;
256x["baz_"] = 3;
257console.log(x.calc());
258```
259Mangle all properties (except for JavaScript `builtins`):
260```bash
261$ terser example.js -c -m --mangle-props
262```
263```javascript
264var x={o:0,_:1,l:function(){return this._+this.o}};x.t=2,x.o=3,console.log(x.l());
265```
266Mangle all properties except for `reserved` properties:
267```bash
268$ terser example.js -c -m --mangle-props reserved=[foo_,bar_]
269```
270```javascript
271var x={o:0,foo_:1,_:function(){return this.foo_+this.o}};x.bar_=2,x.o=3,console.log(x._());
272```
273Mangle all properties matching a `regex`:
274```bash
275$ terser example.js -c -m --mangle-props regex=/_$/
276```
277```javascript
278var x={o:0,_:1,calc:function(){return this._+this.o}};x.l=2,x.o=3,console.log(x.calc());
279```
280
281Combining mangle properties options:
282```bash
283$ terser example.js -c -m --mangle-props regex=/_$/,reserved=[bar_]
284```
285```javascript
286var x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log(x.calc());
287```
288
289In order for this to be of any use, we avoid mangling standard JS names by
290default (`--mangle-props builtins` to override).
291
292A default exclusion file is provided in `tools/domprops.json` which should
293cover most standard JS and DOM properties defined in various browsers. Pass
294`--mangle-props domprops` to disable this feature.
295
296A regular expression can be used to define which property names should be
297mangled. For example, `--mangle-props regex=/^_/` will only mangle property
298names that start with an underscore.
299
300When you compress multiple files using this option, in order for them to
301work together in the end we need to ensure somehow that one property gets
302mangled to the same name in all of them. For this, pass `--name-cache filename.json`
303and Terser will maintain these mappings in a file which can then be reused.
304It should be initially empty. Example:
305
306```bash
307$ rm -f /tmp/cache.json # start fresh
308$ terser file1.js file2.js --mangle-props --name-cache /tmp/cache.json -o part1.js
309$ terser file3.js file4.js --mangle-props --name-cache /tmp/cache.json -o part2.js
310```
311
312Now, `part1.js` and `part2.js` will be consistent with each other in terms
313of mangled property names.
314
315Using the name cache is not necessary if you compress all your files in a
316single call to Terser.
317
318### Mangling unquoted names (`--mangle-props keep_quoted`)
319
320Using quoted property name (`o["foo"]`) reserves the property name (`foo`)
321so that it is not mangled throughout the entire script even when used in an
322unquoted style (`o.foo`). Example:
323
324```javascript
325// stuff.js
326var o = {
327 "foo": 1,
328 bar: 3
329};
330o.foo += o.bar;
331console.log(o.foo);
332```
333```bash
334$ terser stuff.js --mangle-props keep_quoted -c -m
335```
336```javascript
337var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
338```
339
340### Debugging property name mangling
341
342You can also pass `--mangle-props debug` in order to mangle property names
343without completely obscuring them. For example the property `o.foo`
344would mangle to `o._$foo$_` with this option. This allows property mangling
345of a large codebase while still being able to debug the code and identify
346where mangling is breaking things.
347
348```bash
349$ terser stuff.js --mangle-props debug -c -m
350```
351```javascript
352var o={_$foo$_:1,_$bar$_:3};o._$foo$_+=o._$bar$_,console.log(o._$foo$_);
353```
354
355You can also pass a custom suffix using `--mangle-props debug=XYZ`. This would then
356mangle `o.foo` to `o._$foo$XYZ_`. You can change this each time you compile a
357script to identify how a property got mangled. One technique is to pass a
358random number on every compile to simulate mangling changing with different
359inputs (e.g. as you update the input script with new properties), and to help
360identify mistakes like writing mangled keys to storage.
361
362
363# API Reference
364
365Assuming installation via NPM, you can load Terser in your application
366like this:
367```javascript
368var Terser = require("terser");
369```
370
371There is a single high level function, **`minify(code, options)`**,
372which will perform all minification [phases](#minify-options) in a configurable
373manner. By default `minify()` will enable the options [`compress`](#compress-options)
374and [`mangle`](#mangle-options). Example:
375```javascript
376var code = "function add(first, second) { return first + second; }";
377var result = Terser.minify(code);
378console.log(result.error); // runtime error, or `undefined` if no error
379console.log(result.code); // minified output: function add(n,d){return n+d}
380```
381
382You can `minify` more than one JavaScript file at a time by using an object
383for the first argument where the keys are file names and the values are source
384code:
385```javascript
386var code = {
387 "file1.js": "function add(first, second) { return first + second; }",
388 "file2.js": "console.log(add(1 + 2, 3 + 4));"
389};
390var result = Terser.minify(code);
391console.log(result.code);
392// function add(d,n){return d+n}console.log(add(3,7));
393```
394
395The `toplevel` option:
396```javascript
397var code = {
398 "file1.js": "function add(first, second) { return first + second; }",
399 "file2.js": "console.log(add(1 + 2, 3 + 4));"
400};
401var options = { toplevel: true };
402var result = Terser.minify(code, options);
403console.log(result.code);
404// console.log(3+7);
405```
406
407The `nameCache` option:
408```javascript
409var options = {
410 mangle: {
411 toplevel: true,
412 },
413 nameCache: {}
414};
415var result1 = Terser.minify({
416 "file1.js": "function add(first, second) { return first + second; }"
417}, options);
418var result2 = Terser.minify({
419 "file2.js": "console.log(add(1 + 2, 3 + 4));"
420}, options);
421console.log(result1.code);
422// function n(n,r){return n+r}
423console.log(result2.code);
424// console.log(n(3,7));
425```
426
427You may persist the name cache to the file system in the following way:
428```javascript
429var cacheFileName = "/tmp/cache.json";
430var options = {
431 mangle: {
432 properties: true,
433 },
434 nameCache: JSON.parse(fs.readFileSync(cacheFileName, "utf8"))
435};
436fs.writeFileSync("part1.js", Terser.minify({
437 "file1.js": fs.readFileSync("file1.js", "utf8"),
438 "file2.js": fs.readFileSync("file2.js", "utf8")
439}, options).code, "utf8");
440fs.writeFileSync("part2.js", Terser.minify({
441 "file3.js": fs.readFileSync("file3.js", "utf8"),
442 "file4.js": fs.readFileSync("file4.js", "utf8")
443}, options).code, "utf8");
444fs.writeFileSync(cacheFileName, JSON.stringify(options.nameCache), "utf8");
445```
446
447An example of a combination of `minify()` options:
448```javascript
449var code = {
450 "file1.js": "function add(first, second) { return first + second; }",
451 "file2.js": "console.log(add(1 + 2, 3 + 4));"
452};
453var options = {
454 toplevel: true,
455 compress: {
456 global_defs: {
457 "@console.log": "alert"
458 },
459 passes: 2
460 },
461 output: {
462 preamble: "/* minified */"
463 }
464};
465var result = Terser.minify(code, options);
466console.log(result.code);
467// /* minified */
468// alert(10);"
469```
470
471To produce warnings:
472```javascript
473var code = "function f(){ var u; return 2 + 3; }";
474var options = { warnings: true };
475var result = Terser.minify(code, options);
476console.log(result.error); // runtime error, `undefined` in this case
477console.log(result.warnings); // [ 'Dropping unused variable u [0:1,18]' ]
478console.log(result.code); // function f(){return 5}
479```
480
481An error example:
482```javascript
483var result = Terser.minify({"foo.js" : "if (0) else console.log(1);"});
484console.log(JSON.stringify(result.error));
485// {"message":"Unexpected token: keyword (else)","filename":"foo.js","line":1,"col":7,"pos":7}
486```
487Note: unlike `uglify-js@2.x`, the Terser API does not throw errors.
488To achieve a similar effect one could do the following:
489```javascript
490var result = Terser.minify(code, options);
491if (result.error) throw result.error;
492```
493
494## Minify options
495
496- `ecma` (default `undefined`) - pass `5`, `6`, `7` or `8` to override `parse`,
497 `compress` and `output` options.
498
499- `warnings` (default `false`) — pass `true` to return compressor warnings
500 in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
501
502- `parse` (default `{}`) — pass an object if you wish to specify some
503 additional [parse options](#parse-options).
504
505- `compress` (default `{}`) — pass `false` to skip compressing entirely.
506 Pass an object to specify custom [compress options](#compress-options).
507
508- `mangle` (default `true`) — pass `false` to skip mangling names, or pass
509 an object to specify [mangle options](#mangle-options) (see below).
510
511 - `mangle.properties` (default `false`) — a subcategory of the mangle option.
512 Pass an object to specify custom [mangle property options](#mangle-properties-options).
513
514- `module` (default `false`) — Use when minifying an ES6 module. "use strict"
515 is implied and names can be mangled on the top scope. If `compress` or
516 `mangle` is enabled then the `toplevel` option will be enabled.
517
518- `output` (default `null`) — pass an object if you wish to specify
519 additional [output options](#output-options). The defaults are optimized
520 for best compression.
521
522- `sourceMap` (default `false`) - pass an object if you wish to specify
523 [source map options](#source-map-options).
524
525- `toplevel` (default `false`) - set to `true` if you wish to enable top level
526 variable and function name mangling and to drop unused variables and functions.
527
528- `nameCache` (default `null`) - pass an empty object `{}` or a previously
529 used `nameCache` object if you wish to cache mangled variable and
530 property names across multiple invocations of `minify()`. Note: this is
531 a read/write property. `minify()` will read the name cache state of this
532 object and update it during minification so that it may be
533 reused or externally persisted by the user.
534
535- `ie8` (default `false`) - set to `true` to support IE8.
536
537- `keep_classnames` (default: `undefined`) - pass `true` to prevent discarding or mangling
538 of class names. Pass a regular expression to only keep class names matching that regex.
539
540- `keep_fnames` (default: `false`) - pass `true` to prevent discarding or mangling
541 of function names. Pass a regular expression to only keep class names matching that regex.
542 Useful for code relying on `Function.prototype.name`. If the top level minify option
543 `keep_classnames` is `undefined` it will be overridden with the value of the top level
544 minify option `keep_fnames`.
545
546- `safari10` (default: `false`) - pass `true` to work around Safari 10/11 bugs in
547 loop scoping and `await`. See `safari10` options in [`mangle`](#mangle-options)
548 and [`output`](#output-options) for details.
549
550## Minify options structure
551
552```javascript
553{
554 parse: {
555 // parse options
556 },
557 compress: {
558 // compress options
559 },
560 mangle: {
561 // mangle options
562
563 properties: {
564 // mangle property options
565 }
566 },
567 output: {
568 // output options
569 },
570 sourceMap: {
571 // source map options
572 },
573 ecma: 5, // specify one of: 5, 6, 7 or 8
574 keep_classnames: false,
575 keep_fnames: false,
576 ie8: false,
577 module: false,
578 nameCache: null, // or specify a name cache object
579 safari10: false,
580 toplevel: false,
581 warnings: false,
582}
583```
584
585### Source map options
586
587To generate a source map:
588```javascript
589var result = Terser.minify({"file1.js": "var a = function() {};"}, {
590 sourceMap: {
591 filename: "out.js",
592 url: "out.js.map"
593 }
594});
595console.log(result.code); // minified output
596console.log(result.map); // source map
597```
598
599Note that the source map is not saved in a file, it's just returned in
600`result.map`. The value passed for `sourceMap.url` is only used to set
601`//# sourceMappingURL=out.js.map` in `result.code`. The value of
602`filename` is only used to set `file` attribute (see [the spec][sm-spec])
603in source map file.
604
605You can set option `sourceMap.url` to be `"inline"` and source map will
606be appended to code.
607
608You can also specify sourceRoot property to be included in source map:
609```javascript
610var result = Terser.minify({"file1.js": "var a = function() {};"}, {
611 sourceMap: {
612 root: "http://example.com/src",
613 url: "out.js.map"
614 }
615});
616```
617
618If you're compressing compiled JavaScript and have a source map for it, you
619can use `sourceMap.content`:
620```javascript
621var result = Terser.minify({"compiled.js": "compiled code"}, {
622 sourceMap: {
623 content: "content from compiled.js.map",
624 url: "minified.js.map"
625 }
626});
627// same as before, it returns `code` and `map`
628```
629
630If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.url`.
631
632## Parse options
633
634- `bare_returns` (default `false`) -- support top level `return` statements
635
636- `ecma` (default: `8`) -- specify one of `5`, `6`, `7` or `8`. Note: this setting
637 is not presently enforced except for ES8 optional trailing commas in function
638 parameter lists and calls with `ecma` `8`.
639
640- `html5_comments` (default `true`)
641
642- `shebang` (default `true`) -- support `#!command` as the first line
643
644## Compress options
645
646- `arrows` (default: `true`) -- Converts `()=>{return x}` to `()=>x`. Class
647 and object literal methods will also be converted to arrow expressions if
648 the resultant code is shorter: `m(){return x}` becomes `m:()=>x`.
649
650- `arguments` (default: `false`) -- replace `arguments[index]` with function
651 parameter name whenever possible.
652
653- `booleans` (default: `true`) -- various optimizations for boolean context,
654 for example `!!a ? b : c → a ? b : c`
655
656- `booleans_as_integers` (default: `false`) -- Turn booleans into 0 and 1, also
657 makes comparisons with booleans use `==` and `!=` instead of `===` and `!==`.
658
659- `collapse_vars` (default: `true`) -- Collapse single-use non-constant variables,
660 side effects permitting.
661
662- `comparisons` (default: `true`) -- apply certain optimizations to binary nodes,
663 e.g. `!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary
664 nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
665
666- `computed_props` (default: `true`) -- Transforms constant computed properties
667 into regular ones: `{["computed"]: 1}` is converted to `{computed: 1}`.
668
669- `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional
670 expressions
671
672- `dead_code` (default: `true`) -- remove unreachable code
673
674- `defaults` (default: `true`) -- Pass `false` to disable most default
675 enabled `compress` transforms. Useful when you only want to enable a few
676 `compress` options while disabling the rest.
677
678- `directives` (default: `true`) -- remove redundant or non-standard directives
679
680- `drop_console` (default: `false`) -- Pass `true` to discard calls to
681 `console.*` functions. If you wish to drop a specific function call
682 such as `console.info` and/or retain side effects from function arguments
683 after dropping the function call then use `pure_funcs` instead.
684
685- `drop_debugger` (default: `true`) -- remove `debugger;` statements
686
687- `ecma` (default: `5`) -- Pass `6` or greater to enable `compress` options that
688 will transform ES5 code into smaller ES6+ equivalent forms.
689
690- `evaluate` (default: `true`) -- attempt to evaluate constant expressions
691
692- `expression` (default: `false`) -- Pass `true` to preserve completion values
693 from terminal statements without `return`, e.g. in bookmarklets.
694
695- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
696
697- `hoist_funs` (default: `false`) -- hoist function declarations
698
699- `hoist_props` (default: `true`) -- hoist properties from constant object and
700 array literals into regular variables subject to a set of constraints. For example:
701 `var o={p:1, q:2}; f(o.p, o.q);` is converted to `f(1, 2);`. Note: `hoist_props`
702 works best with `mangle` enabled, the `compress` option `passes` set to `2` or higher,
703 and the `compress` option `toplevel` enabled.
704
705- `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false`
706 by default because it seems to increase the size of the output in general)
707
708- `if_return` (default: `true`) -- optimizations for if/return and if/continue
709
710- `inline` (default: `true`) -- inline calls to function with simple/`return` statement:
711 - `false` -- same as `0`
712 - `0` -- disabled inlining
713 - `1` -- inline simple functions
714 - `2` -- inline functions with arguments
715 - `3` -- inline functions with arguments and variables
716 - `true` -- same as `3`
717
718- `join_vars` (default: `true`) -- join consecutive `var` statements
719
720- `keep_classnames` (default: `false`) -- Pass `true` to prevent the compressor from
721 discarding class names. Pass a regular expression to only keep class names matching
722 that regex. See also: the `keep_classnames` [mangle option](#mangle).
723
724- `keep_fargs` (default: `true`) -- Prevents the compressor from discarding unused
725 function arguments. You need this for code which relies on `Function.length`.
726
727- `keep_fnames` (default: `false`) -- Pass `true` to prevent the
728 compressor from discarding function names. Pass a regular expression to only keep
729 class names matching that regex. Useful for code relying on `Function.prototype.name`.
730 See also: the `keep_fnames` [mangle option](#mangle).
731
732- `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
733 being compressed into `1/0`, which may cause performance issues on Chrome.
734
735- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops
736 when we can statically determine the condition.
737
738- `module` (default `false`) -- Pass `true` when compressing an ES6 module. Strict
739 mode is implied and the `toplevel` option as well.
740
741- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
742 where the return value is discarded, to avoid the parens that the
743 code generator would insert.
744
745- `passes` (default: `1`) -- The maximum number of times to run compress.
746 In some cases more than one pass leads to further compressed code. Keep in
747 mind more passes will take more time.
748
749- `properties` (default: `true`) -- rewrite property access using the dot notation, for
750 example `foo["bar"] → foo.bar`
751
752- `pure_funcs` (default: `null`) -- You can pass an array of names and
753 Terser will assume that those functions do not produce side
754 effects. DANGER: will not check if the name is redefined in scope.
755 An example case here, for instance `var q = Math.floor(a/b)`. If
756 variable `q` is not used elsewhere, Terser will drop it, but will
757 still keep the `Math.floor(a/b)`, not knowing what it does. You can
758 pass `pure_funcs: [ 'Math.floor' ]` to let it know that this
759 function won't produce any side effect, in which case the whole
760 statement would get discarded. The current implementation adds some
761 overhead (compression will be slower).
762
763- `pure_getters` (default: `"strict"`) -- If you pass `true` for
764 this, Terser will assume that object property access
765 (e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
766 Specify `"strict"` to treat `foo.bar` as side-effect-free only when
767 `foo` is certain to not throw, i.e. not `null` or `undefined`.
768
769- `reduce_funcs` (default: `true`) -- Allows single-use functions to be
770 inlined as function expressions when permissible allowing further
771 optimization. Enabled by default. Option depends on `reduce_vars`
772 being enabled. Some code runs faster in the Chrome V8 engine if this
773 option is disabled. Does not negatively impact other major browsers.
774
775- `reduce_vars` (default: `true`) -- Improve optimization on variables assigned with and
776 used as constant values.
777
778- `sequences` (default: `true`) -- join consecutive simple statements using the
779 comma operator. May be set to a positive integer to specify the maximum number
780 of consecutive comma sequences that will be generated. If this option is set to
781 `true` then the default `sequences` limit is `200`. Set option to `false` or `0`
782 to disable. The smallest `sequences` length is `2`. A `sequences` value of `1`
783 is grandfathered to be equivalent to `true` and as such means `200`. On rare
784 occasions the default sequences limit leads to very slow compress times in which
785 case a value of `20` or less is recommended.
786
787- `side_effects` (default: `true`) -- Pass `false` to disable potentially dropping
788 functions marked as "pure". A function call is marked as "pure" if a comment
789 annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
790 example: `/*@__PURE__*/foo();`
791
792- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
793
794- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
795 variables (`"vars"`) in the top level scope (`false` by default, `true` to drop
796 both unreferenced functions and variables)
797
798- `top_retain` (default: `null`) -- prevent specific toplevel functions and
799 variables from `unused` removal (can be array, comma-separated, RegExp or
800 function. Implies `toplevel`)
801
802- `typeofs` (default: `true`) -- Transforms `typeof foo == "undefined"` into
803 `foo === void 0`. Note: recommend to set this value to `false` for IE10 and
804 earlier versions due to known issues.
805
806- `unsafe` (default: `false`) -- apply "unsafe" transformations
807 ([details](#the-unsafe-compress-option)).
808
809- `unsafe_arrows` (default: `false`) -- Convert ES5 style anonymous function
810 expressions to arrow functions if the function body does not reference `this`.
811 Note: it is not always safe to perform this conversion if code relies on the
812 the function having a `prototype`, which arrow functions lack.
813 This transform requires that the `ecma` compress option is set to `6` or greater.
814
815- `unsafe_comps` (default: `false`) -- Reverse `<` and `<=` to `>` and `>=` to
816 allow improved compression. This might be unsafe when an at least one of two
817 operands is an object with computed values due the use of methods like `get`,
818 or `valueOf`. This could cause change in execution order after operands in the
819 comparison are switching. Compression only works if both `comparisons` and
820 `unsafe_comps` are both set to true.
821
822- `unsafe_Function` (default: `false`) -- compress and mangle `Function(args, code)`
823 when both `args` and `code` are string literals.
824
825- `unsafe_math` (default: `false`) -- optimize numerical expressions like
826 `2 * x * 3` into `6 * x`, which may give imprecise floating point results.
827
828- `unsafe_methods` (default: false) -- Converts `{ m: function(){} }` to
829 `{ m(){} }`. `ecma` must be set to `6` or greater to enable this transform.
830 If `unsafe_methods` is a RegExp then key/value pairs with keys matching the
831 RegExp will be converted to concise methods.
832 Note: if enabled there is a risk of getting a "`<method name>` is not a
833 constructor" TypeError should any code try to `new` the former function.
834
835- `unsafe_proto` (default: `false`) -- optimize expressions like
836 `Array.prototype.slice.call(a)` into `[].slice.call(a)`
837
838- `unsafe_regexp` (default: `false`) -- enable substitutions of variables with
839 `RegExp` values the same way as if they are constants.
840
841- `unsafe_undefined` (default: `false`) -- substitute `void 0` if there is a
842 variable named `undefined` in scope (variable name will be mangled, typically
843 reduced to a single character)
844
845- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
846 direct variable assignments do not count as references unless set to `"keep_assign"`)
847
848- `warnings` (default: `false`) -- display warnings when dropping unreachable
849 code or unused declarations etc.
850
851## Mangle options
852
853- `eval` (default `false`) -- Pass `true` to mangle names visible in scopes
854 where `eval` or `with` are used.
855
856- `keep_classnames` (default `false`) -- Pass `true` to not mangle class names.
857 Pass a regular expression to only keep class names matching that regex.
858 See also: the `keep_classnames` [compress option](#compress-options).
859
860- `keep_fnames` (default `false`) -- Pass `true` to not mangle function names.
861 Pass a regular expression to only keep class names matching that regex.
862 Useful for code relying on `Function.prototype.name`. See also: the `keep_fnames`
863 [compress option](#compress-options).
864
865- `module` (default `false`) -- Pass `true` an ES6 modules, where the toplevel
866 scope is not the global scope. Implies `toplevel`.
867
868- `reserved` (default `[]`) -- Pass an array of identifiers that should be
869 excluded from mangling. Example: `["foo", "bar"]`.
870
871- `toplevel` (default `false`) -- Pass `true` to mangle names declared in the
872 top level scope.
873
874- `safari10` (default `false`) -- Pass `true` to work around the Safari 10 loop
875 iterator [bug](https://bugs.webkit.org/show_bug.cgi?id=171041)
876 "Cannot declare a let variable twice".
877 See also: the `safari10` [output option](#output-options).
878
879Examples:
880
881```javascript
882// test.js
883var globalVar;
884function funcName(firstLongName, anotherLongName) {
885 var myVariable = firstLongName + anotherLongName;
886}
887```
888```javascript
889var code = fs.readFileSync("test.js", "utf8");
890
891Terser.minify(code).code;
892// 'function funcName(a,n){}var globalVar;'
893
894Terser.minify(code, { mangle: { reserved: ['firstLongName'] } }).code;
895// 'function funcName(firstLongName,a){}var globalVar;'
896
897Terser.minify(code, { mangle: { toplevel: true } }).code;
898// 'function n(n,a){}var a;'
899```
900
901### Mangle properties options
902
903- `builtins` (default: `false`) -- Use `true` to allow the mangling of builtin
904 DOM properties. Not recommended to override this setting.
905
906- `debug` (default: `false`) -— Mangle names with the original name still present.
907 Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
908
909- `keep_quoted` (default: `false`) -— Only mangle unquoted property names.
910
911- `regex` (default: `null`) -— Pass a RegExp literal to only mangle property
912 names matching the regular expression.
913
914- `reserved` (default: `[]`) -- Do not mangle property names listed in the
915 `reserved` array.
916
917## Output options
918
919The code generator tries to output shortest code possible. Optionally you
920can pass additional arguments that control the code output:
921
922- `ascii_only` (default `false`) -- escape Unicode characters in strings and
923 regexps (affects directives with non-ascii characters becoming invalid)
924
925- `braces` (default `false`) -- always insert braces in `if`, `for`,
926 `do`, `while` or `with` statements, even if their body is a single
927 statement.
928
929- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
930 comments, `"some"` to preserve some comments, a regular expression string
931 (e.g. `/^!/`) or a function.
932
933- `ecma` (default `5`) -- set output printing mode. Set `ecma` to `6` or
934 greater to emit shorthand object properties - i.e.: `{a}` instead of `{a: a}`.
935 Non-compatible features in the abstract syntax tree will still
936 be output as is. For example: an `ecma` setting of `5` will **not** convert
937 ES6+ code to ES5.
938
939- `indent_level` (default `4`)
940
941- `indent_start` (default `0`) -- prefix all lines by that many spaces
942
943- `inline_script` (default `true`) -- escape HTML comments and the slash in
944 occurrences of `</script>` in strings
945
946- `keep_quoted_props` (default `false`) -- when turned on, prevents stripping
947 quotes from property names in object literals.
948
949- `max_line_len` (default `false`) -- maximum line length (for minified code)
950
951- `preamble` (default `null`) -- when passed it must be a string and
952 it will be prepended to the output literally. The source map will
953 adjust for this text. Can be used to insert a comment containing
954 licensing information, for example.
955
956- `quote_keys` (default `false`) -- pass `true` to quote all keys in literal
957 objects
958
959- `quote_style` (default `0`) -- preferred quote style for strings (affects
960 quoted property names and directives as well):
961 - `0` -- prefers double quotes, switches to single quotes when there are
962 more double quotes in the string itself. `0` is best for gzip size.
963 - `1` -- always use single quotes
964 - `2` -- always use double quotes
965 - `3` -- always use the original quotes
966
967- `safari10` (default `false`) -- set this option to `true` to work around
968 the [Safari 10/11 await bug](https://bugs.webkit.org/show_bug.cgi?id=176685).
969 See also: the `safari10` [mangle option](#mangle-options).
970
971- `semicolons` (default `true`) -- separate statements with semicolons. If
972 you pass `false` then whenever possible we will use a newline instead of a
973 semicolon, leading to more readable output of minified code (size before
974 gzip could be smaller; size after gzip insignificantly larger).
975
976- `shebang` (default `true`) -- preserve shebang `#!` in preamble (bash scripts)
977
978- `webkit` (default `false`) -- enable workarounds for WebKit bugs.
979 PhantomJS users should set this option to `true`.
980
981- `wrap_iife` (default `false`) -- pass `true` to wrap immediately invoked
982 function expressions. See
983 [#640](https://github.com/mishoo/UglifyJS2/issues/640) for more details.
984
985# Miscellaneous
986
987### Keeping copyright notices or other comments
988
989You can pass `--comments` to retain certain comments in the output. By
990default it will keep JSDoc-style comments that contain "@preserve",
991"@license" or "@cc_on" (conditional compilation for IE). You can pass
992`--comments all` to keep all the comments, or a valid JavaScript regexp to
993keep only comments that match this regexp. For example `--comments /^!/`
994will keep comments like `/*! Copyright Notice */`.
995
996Note, however, that there might be situations where comments are lost. For
997example:
998```javascript
999function f() {
1000 /** @preserve Foo Bar */
1001 function g() {
1002 // this function is never called
1003 }
1004 return something();
1005}
1006```
1007
1008Even though it has "@preserve", the comment will be lost because the inner
1009function `g` (which is the AST node to which the comment is attached to) is
1010discarded by the compressor as not referenced.
1011
1012The safest comments where to place copyright information (or other info that
1013needs to be kept in the output) are comments attached to toplevel nodes.
1014
1015### The `unsafe` `compress` option
1016
1017It enables some transformations that *might* break code logic in certain
1018contrived cases, but should be fine for most code. It assumes that standard
1019built-in ECMAScript functions and classes have not been altered or replaced.
1020You might want to try it on your own code; it should reduce the minified size.
1021Some examples of the optimizations made when this option is enabled:
1022
1023- `new Array(1, 2, 3)` or `Array(1, 2, 3)``[ 1, 2, 3 ]`
1024- `new Object()``{}`
1025- `String(exp)` or `exp.toString()``"" + exp`
1026- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
1027- `"foo bar".substr(4)``"bar"`
1028
1029### Conditional compilation
1030
1031You can use the `--define` (`-d`) switch in order to declare global
1032variables that Terser will assume to be constants (unless defined in
1033scope). For example if you pass `--define DEBUG=false` then, coupled with
1034dead code removal Terser will discard the following from the output:
1035```javascript
1036if (DEBUG) {
1037 console.log("debug stuff");
1038}
1039```
1040
1041You can specify nested constants in the form of `--define env.DEBUG=false`.
1042
1043Terser will warn about the condition being always false and about dropping
1044unreachable code; for now there is no option to turn off only this specific
1045warning, you can pass `warnings=false` to turn off *all* warnings.
1046
1047Another way of doing that is to declare your globals as constants in a
1048separate file and include it into the build. For example you can have a
1049`build/defines.js` file with the following:
1050```javascript
1051var DEBUG = false;
1052var PRODUCTION = true;
1053// etc.
1054```
1055
1056and build your code like this:
1057
1058 terser build/defines.js js/foo.js js/bar.js... -c
1059
1060Terser will notice the constants and, since they cannot be altered, it
1061will evaluate references to them to the value itself and drop unreachable
1062code as usual. The build will contain the `const` declarations if you use
1063them. If you are targeting < ES6 environments which does not support `const`,
1064using `var` with `reduce_vars` (enabled by default) should suffice.
1065
1066### Conditional compilation API
1067
1068You can also use conditional compilation via the programmatic API. With the difference that the
1069property name is `global_defs` and is a compressor property:
1070
1071```javascript
1072var result = Terser.minify(fs.readFileSync("input.js", "utf8"), {
1073 compress: {
1074 dead_code: true,
1075 global_defs: {
1076 DEBUG: false
1077 }
1078 }
1079});
1080```
1081
1082To replace an identifier with an arbitrary non-constant expression it is
1083necessary to prefix the `global_defs` key with `"@"` to instruct Terser
1084to parse the value as an expression:
1085```javascript
1086Terser.minify("alert('hello');", {
1087 compress: {
1088 global_defs: {
1089 "@alert": "console.log"
1090 }
1091 }
1092}).code;
1093// returns: 'console.log("hello");'
1094```
1095
1096Otherwise it would be replaced as string literal:
1097```javascript
1098Terser.minify("alert('hello');", {
1099 compress: {
1100 global_defs: {
1101 "alert": "console.log"
1102 }
1103 }
1104}).code;
1105// returns: '"console.log"("hello");'
1106```
1107
1108### Using native Terser AST with `minify()`
1109```javascript
1110// example: parse only, produce native Terser AST
1111
1112var result = Terser.minify(code, {
1113 parse: {},
1114 compress: false,
1115 mangle: false,
1116 output: {
1117 ast: true,
1118 code: false // optional - faster if false
1119 }
1120});
1121
1122// result.ast contains native Terser AST
1123```
1124```javascript
1125// example: accept native Terser AST input and then compress and mangle
1126// to produce both code and native AST.
1127
1128var result = Terser.minify(ast, {
1129 compress: {},
1130 mangle: {},
1131 output: {
1132 ast: true,
1133 code: true // optional - faster if false
1134 }
1135});
1136
1137// result.ast contains native Terser AST
1138// result.code contains the minified code in string form.
1139```
1140
1141### Working with Terser AST
1142
1143Traversal and transformation of the native AST can be performed through
1144[`TreeWalker`](https://github.com/fabiosantoscode/terser/blob/master/lib/ast.js) and
1145[`TreeTransformer`](https://github.com/fabiosantoscode/terser/blob/master/lib/transform.js)
1146respectively.
1147
1148Largely compatible native AST examples can be found in the original UglifyJS
1149documentation. See: [tree walker](http://lisperator.net/uglifyjs/walk) and
1150[tree transform](http://lisperator.net/uglifyjs/transform).
1151
1152### ESTree / SpiderMonkey AST
1153
1154Terser has its own abstract syntax tree format; for
1155[practical reasons](http://lisperator.net/blog/uglifyjs-why-not-switching-to-spidermonkey-ast/)
1156we can't easily change to using the SpiderMonkey AST internally. However,
1157Terser now has a converter which can import a SpiderMonkey AST.
1158
1159For example [Acorn][acorn] is a super-fast parser that produces a
1160SpiderMonkey AST. It has a small CLI utility that parses one file and dumps
1161the AST in JSON on the standard output. To use Terser to mangle and
1162compress that:
1163
1164 acorn file.js | terser -p spidermonkey -m -c
1165
1166The `-p spidermonkey` option tells Terser that all input files are not
1167JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we
1168don't use our own parser in this case, but just transform that AST into our
1169internal AST.
1170
1171### Use Acorn for parsing
1172
1173More for fun, I added the `-p acorn` option which will use Acorn to do all
1174the parsing. If you pass this option, Terser will `require("acorn")`.
1175
1176Acorn is really fast (e.g. 250ms instead of 380ms on some 650K code), but
1177converting the SpiderMonkey tree that Acorn produces takes another 150ms so
1178in total it's a bit more than just using Terser's own parser.
1179
1180[acorn]: https://github.com/ternjs/acorn
1181[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k
1182
1183### Terser Fast Minify Mode
1184
1185It's not well known, but whitespace removal and symbol mangling accounts
1186for 95% of the size reduction in minified code for most JavaScript - not
1187elaborate code transforms. One can simply disable `compress` to speed up
1188Terser builds by 3 to 4 times.
1189
1190| d3.js | size | gzip size | time (s) |
1191| --- | ---: | ---: | ---: |
1192| original | 451,131 | 108,733 | - |
1193| terser@3.7.5 mangle=false, compress=false | 316,600 | 85,245 | 0.82 |
1194| terser@3.7.5 mangle=true, compress=false | 220,216 | 72,730 | 1.45 |
1195| terser@3.7.5 mangle=true, compress=true | 212,046 | 70,954 | 5.87 |
1196| babili@0.1.4 | 210,713 | 72,140 | 12.64 |
1197| babel-minify@0.4.3 | 210,321 | 72,242 | 48.67 |
1198| babel-minify@0.5.0-alpha.01eac1c3 | 210,421 | 72,238 | 14.17 |
1199
1200To enable fast minify mode from the CLI use:
1201```
1202terser file.js -m
1203```
1204To enable fast minify mode with the API use:
1205```js
1206Terser.minify(code, { compress: false, mangle: true });
1207```
1208
1209#### Source maps and debugging
1210
1211Various `compress` transforms that simplify, rearrange, inline and remove code
1212are known to have an adverse effect on debugging with source maps. This is
1213expected as code is optimized and mappings are often simply not possible as
1214some code no longer exists. For highest fidelity in source map debugging
1215disable the `compress` option and just use `mangle`.
1216
1217### Compiler assumptions
1218
1219To allow for better optimizations, the compiler makes various assumptions:
1220
1221- `.toString()` and `.valueOf()` don't have side effects, and for built-in
1222 objects they have not been overridden.
1223- `undefined`, `NaN` and `Infinity` have not been externally redefined.
1224- `arguments.callee`, `arguments.caller` and `Function.prototype.caller` are not used.
1225- The code doesn't expect the contents of `Function.prototype.toString()` or
1226 `Error.prototype.stack` to be anything in particular.
1227- Getting and setting properties on a plain object does not cause other side effects
1228 (using `.watch()` or `Proxy`).
1229- Object properties can be added, removed and modified (not prevented with
1230 `Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
1231 `Object.preventExtensions()` or `Object.seal()`).
1232
1233### Build Tools and Adaptors using Terser
1234
1235https://www.npmjs.com/browse/depended/terser
1236
1237### Replacing `uglify-es` with `terser` in a project using `yarn`
1238
1239A number of JS bundlers and uglify wrappers are still using buggy versions
1240of `uglify-es` and have not yet upgraded to `terser`. If you are using `yarn`
1241you can add the following alias to your project's `package.json` file:
1242
1243```js
1244 "resolutions": {
1245 "uglify-es": "npm:terser"
1246 }
1247```
1248
1249to use `terser` instead of `uglify-es` in all deeply nested dependencies
1250without changing any code.
1251
1252Note: for this change to take effect you must run the following commands
1253to remove the existing `yarn` lock file and reinstall all packages:
1254
1255```
1256$ rm -rf node_modules yarn.lock
1257$ yarn
1258```
1259
1260# Reporting issues
1261
1262In the terser CLI we use [source-map-support](https://npmjs.com/source-map-support) to produce good error stacks. In your own app, you're expected to enable source-map-support (read their docs) to have nice stack traces that will make good issues.
1263
1264# README.md Patrons:
1265
1266*note*: You can support this project on patreon: <a target="_blank" rel="nofollow" href="https://www.patreon.com/terser_jscomp_maintainer"><img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" alt="patron" width="100px" height="auto"></a>. Check out PATRONS.md for our first-tier patrons.
1267
1268
1269 * CKEditor ![CKEditor](https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/15452278/f8548dcf48d740619071e8d614459280/1?token-time=2145916800&token-hash=SIQ54PhIPHv3M7CVz9LxS8_8v4sOw4H304HaXsXj8MM%3D)
1270