UNPKG

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