UNPKG

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