Projekt

Obecné

Profil

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