UNPKG

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