UglifyJS 3
UglifyJS è un parser JavaScript, un minifier, un compressore e un toolkit di abbellimento.
Nota:
uglify-js@3
ha un'API e una CLI semplificate che non sono retrocompatibili conuglify-js@2
.- La documentazione per le
2.x
versioni di UglifyJS può essere trovata qui . uglify-js
supporta solo JavaScript (ECMAScript 5).- Per minimizzare ECMAScript 2015 o versioni successive, transpile utilizzando strumenti come Babel .
Installare
Innanzitutto assicurati di aver installato l'ultima versione di node.js (potrebbe essere necessario riavviare il computer dopo questo passaggio).
Da NPM per l'utilizzo come app da riga di comando:
1npm install uglify-js -g
Da NPM per uso programmatico:
1npm install uglify-js
Utilizzo della riga di comando
1uglifyjs [input files] [options]
UglifyJS può accettare più file di input. Si consiglia di passare prima i file di input, quindi di passare le opzioni. UglifyJS analizzerà i file di input in sequenza e applicherà tutte le opzioni di compressione. I file vengono analizzati nello stesso ambito globale, ovvero un riferimento da un file ad alcune variabili/funzioni dichiarate in un altro file verranno abbinate correttamente.
Se non viene specificato alcun file di input, UglifyJS leggerà da STDIN.
Se desideri passare le tue opzioni prima dei file di input, separa le due con un doppio trattino per evitare che i file di input vengano utilizzati come argomenti delle opzioni:
1uglifyjs --compress --mangle -- input.js
Command line options
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 -h, --help Print usage information.
`--help options` for details on available options.
-V, --version Print version number.
-p, --parse <options> Specify parser options:
`acorn` Use Acorn for parsing.
`bare_returns` Allow return outside of functions.
Useful when minifying CommonJS
modules and Userscripts that may
be anonymous function wrapped (IIFE)
by the .user.js engine `caller`.
`expression` Parse a single expression, rather than
a program (for parsing JSON).
`spidermonkey` Assume input files are SpiderMonkey
AST format (as JSON).
-c, --compress [options] Enable compressor/specify compressor options:
`pure_funcs` List of functions that can be safely
removed when their return values are
not used.
-m, --mangle [options] Mangle names/specify mangler options:
`reserved` List of names that should not be mangled.
--mangle-props [options] Mangle properties/specify mangler options:
`builtins` Mangle property names that overlaps
with standard JavaScript globals.
`debug` Add debug prefix and suffix.
`domprops` Mangle property names that overlaps
with DOM properties.
`keep_quoted` Only mangle unquoted properties.
`regex` Only mangle matched property names.
`reserved` List of names that should not be mangled.
-b, --beautify [options] Beautify output/specify output options:
`beautify` Enabled with `--beautify` by default.
`preamble` Preamble to prepend to the output. You
can use this to insert a comment, for
example for licensing information.
This will not be parsed, but the source
map will adjust for its presence.
`quote_style` Quote style:
0 - auto
1 - single
2 - double
3 - original
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
want to disable `negate_iife` under
compressor options.
-o, --output <file> Output file path (default STDOUT). Specify `ast` or
`spidermonkey` to write UglifyJS or SpiderMonkey AST
as JSON to STDOUT respectively.
--comments [filter] Preserve copyright comments in the output. By
default this works like Google Closure, keeping
JSDoc-style comments that contain "@license" or
"@preserve". You can optionally pass one of the
following arguments to this flag:
- "all" to keep all comments
- a valid JS RegExp like `/foo/` or `/^!/` to
keep only matching comments.
Note that currently not *all* comments can be
kept when compression is on, because of dead
code removal or cascading statements into
sequences.
--config-file <file> Read `minify()` options from JSON file.
-d, --define <expr>[=value] Global definitions.
--ie8 Support non-standard Internet Explorer 8.
Equivalent to setting `ie8: true` in `minify()`
for `compress`, `mangle` and `output` options.
By default UglifyJS will not try to be IE-proof.
--keep-fnames Do not mangle/drop function names. Useful for
code relying on Function.prototype.name.
--name-cache <file> File to hold mangled name mappings.
--self Build UglifyJS as a library (implies --wrap UglifyJS)
--source-map [options] Enable source map/specify source map options:
`base` Path to compute relative paths from input files.
`content` Input source map, useful if you're compressing
JS that was generated from some other original
code. Specify "inline" if the source map is
included within the sources.
`filename` Name and/or location of the output source.
`includeSources` Pass this flag if you want to include
the content of source files in the
source map as sourcesContent property.
`root` Path to the original source to be included in
the source map.
`url` If specified, path to the source map to append in
`//# sourceMappingURL`.
--timings Display operations run time on STDERR.
--toplevel Compress and/or mangle variables in top level scope.
--verbose Print diagnostic messages.
--warn Print warning messages.
--wrap <name> Embed everything in a big function, making the
“exports” and “global” variables available. You
need to pass an argument to this option to
specify the name that your module will take
when included in, say, a browser.
Specificare --output
( -o
) per dichiarare il file di output, altrimenti l'output va a STDOUT.
Opzioni mappa sorgente CLI
UglifyJS può generare un file di mappa di origine, che è molto utile per il debug del JavaScript compresso.Per ottenere una mappa di origine, passa
--source-map --output output.js
(la mappa di origine verrà scritta in
output.js.map
).
Opzioni aggiuntive:
--source-map "filename='<NAME>'"
per specificare il nome della mappa di origine.--source-map "root='<URL>'"
per passare l'URL in cui è possibile trovare i file originali.--source-map "url='<URL>'"
per specificare l'URL in cui è possibile trovare la mappa di origine, altrimenti UglifyJS presume cheX-SourceMap
venga utilizzato HTTP e ometterà la//# sourceMappingURL=
direttiva.
Per esempio:
1
2
3uglifyjs js/file1.js js/file2.js \
-o foo.min.js -c -m \
--source-map "root='http://foo.com/src',url='foo.min.js.map'"
Quanto sopra comprimerà e modificherà file1.js
e file2.js
, rilascerà l'output foo.min.js
e la mappa di origine in foo.min.js.map
. La mappatura di origine farà riferimento a http://foo.com/src/js/file1.js
e
http://foo.com/src/js/file2.js
(infatti elencherà http://foo.com/src
come radice della mappa di origine e i file originali come js/file1.js
e
js/file2.js
).
Composed source map
Quando stai comprimendo il codice JS che è stato prodotto da un compilatore come CoffeeScript, la mappatura al codice JS non sarà molto utile.Invece, vorresti mappare di nuovo al codice originale (es. CoffeeScript).UglifyJS ha un opzione per prendere una mappa sorgente di input.Supponendo che tu abbia una mappatura da CoffeeScript → JS compilato, UglifyJS può generare una mappa da CoffeeScript → JS compresso mappando ogni token nel JS compilato nella sua posizione originale.
Per utilizzare questa funzionalità passa --source-map "content='/path/to/input/source.map'"
o --source-map "content=inline"
se la mappa di origine è inclusa in linea con le origini.
Opzioni di compressione CLI
Devi passare --compress
( -c
) per abilitare il compressore.Facoltativamente puoi passare un elenco separato da virgole di opzioni di compressione .
Le opzioni sono nella forma foo=bar
, o semplicemente foo
(quest'ultima implica un'opzione booleana che si desidera impostare true
; è effettivamente una scorciatoia per foo=true
).
Esempio:
1uglifyjs file.js -c toplevel,sequences=false
Opzioni di modifica della CLI
Per abilitare il mangler è necessario passare --mangle
( -m
).Sono supportate le seguenti opzioni (separate da virgole):
toplevel
(defaultfalse
) - nomi di mangle dichiarati nell'ambito di livello superiore.eval
(predefinitofalse
) - nomi mangle visibili negli ambiti in cuieval
owith
vengono utilizzati.
Quando la manipolazione è abilitata ma si desidera impedire che determinati nomi vengano modificati, è possibile dichiarare tali nomi con --mangle reserved
— passare un elenco di nomi separato da virgole, ad esempio:
1uglifyjs ... -m reserved=['$','require','exports']
per evitare che i nomi require
, exports
e $
vengano modificati.
Nomi delle proprietà di manipolazione della CLI ( --mangle-props
)
Nota: PROBABILMENTE QUESTO DANNEGGIERA' IL TUO CODICE. La manipolazione dei nomi delle proprietà è un passaggio separato, diverso dalla modifica dei nomi delle variabili. Passa
--mangle-props
per abilitarlo. Distorcerà tutte le proprietà nel codice di input ad eccezione delle proprietà DOM integrate e delle proprietà nel JavaScript di base classi. Ad esempio:
1
2
3
4
5
6
7
8
9
10
11// example.js
var x = {
baz_: 0,
foo_: 1,
calc: function() {
return this.foo_ + this.baz_;
}
};
x.bar_ = 2;
x["baz_"] = 3;
console.log(x.calc());
Modifica tutte le proprietà (eccetto JavaScript builtins
):
1$ uglifyjs example.js -c -m --mangle-props
1var x={o:0,_:1,l:function(){return this._+this.o}};x.t=2,x.o=3,console.log(x.l());
Modifica tutte le proprietà tranne le reserved
proprietà:
1$ uglifyjs example.js -c -m --mangle-props reserved=[foo_,bar_]
1var x={o:0,foo_:1,_:function(){return this.foo_+this.o}};x.bar_=2,x.o=3,console.log(x._());
Mangle tutte le proprietà che corrispondono a regex
:
1$ uglifyjs example.js -c -m --mangle-props regex=/_$/
1var x={o:0,_:1,calc:function(){return this._+this.o}};x.l=2,x.o=3,console.log(x.calc());
Combinazione delle opzioni delle proprietà del mangano:
1$ uglifyjs example.js -c -m --mangle-props regex=/_$/,reserved=[bar_]
1var x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log(x.calc());
Affinché ciò sia di qualche utilità, evitiamo di modificare i nomi JS standard per impostazione predefinita ( --mangle-props builtins
da sovrascrivere).
Viene fornito un file di esclusione predefinito in tools/domprops.json
cui dovrebbe coprire la maggior parte delle proprietà JS e DOM standard definite nei vari browser.Passare
--mangle-props domprops
per disabilitare questa funzione.
Un'espressione regolare può essere utilizzata per definire quali nomi di proprietà devono essere modificati.Ad esempio, --mangle-props regex=/^_/
verranno modificati solo i nomi di proprietà che iniziano con un carattere di sottolineatura.
Quando comprimi più file usando questa opzione, affinché possano funzionare insieme alla fine dobbiamo assicurarci che una proprietà venga modificata con lo stesso nome in tutti --name-cache filename.json
loro.Per questo, pass e UglifyJS manterrà queste mappature in un file che può essere riutilizzato. Inizialmente dovrebbe essere vuoto. Esempio:
1
2
3$ rm -f /tmp/cache.json # start fresh
$ uglifyjs file1.js file2.js --mangle-props --name-cache /tmp/cache.json -o part1.js
$ uglifyjs file3.js file4.js --mangle-props --name-cache /tmp/cache.json -o part2.js
Ora, part1.js
e part2.js
saranno coerenti tra loro in termini di nomi di proprietà alterati.
L'uso della cache dei nomi non è necessario se comprimi tutti i tuoi file in una singola chiamata a UglifyJS.
Distorcere i nomi non quotati ( --mangle-props keep_quoted
)
L'utilizzo del nome della proprietà tra virgolette ( o["foo"]
) riserva il nome della proprietà ( foo
) in modo che non venga alterato nell'intero script anche se utilizzato in uno stile senza virgolette ( o.foo
).
1
2
3
4
5
6
7// stuff.js
var o = {
"foo": 1,
bar: 3
};
o.foo += o.bar;
console.log(o.foo);
1$ uglifyjs stuff.js --mangle-props keep_quoted -c -m
1var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
Debugging property name mangling
Puoi anche passare --mangle-props debug
per manipolare i nomi delle proprietà senza oscurarli completamente. Ad esempio, la proprietà o.foo
potrebbe essere modificata o._$foo$_
con questa opzione. Ciò consente la manipolazione delle proprietà di una grande base di codice pur essendo in grado di eseguire il debug del codice e identificare dove la manipolazione sta rompendo le cose.
1$ uglifyjs stuff.js --mangle-props debug -c -m
1var o={_$foo$_:1,_$bar$_:3};o._$foo$_+=o._$bar$_,console.log(o._$foo$_);
Puoi anche passare un suffisso personalizzato usando --mangle-props debug=XYZ
.Questo sarebbe quindi mangle o.foo
in .Puoi o._$foo$XYZ_
cambiarlo ogni volta che compili uno script per identificare come una proprietà è stata alterata.Una tecnica consiste nel passare un numero casuale su ogni compilazione per simulare il cambiamento di mangling con diversi input (ad esempio quando si aggiorna lo script di input con nuove proprietà) e per aiutare a identificare errori come la scrittura di chiavi alterate nell'archivio.
Riferimento API
Supponendo l'installazione tramite NPM, puoi caricare UglifyJS nella tua applicazione in questo modo:
1var UglifyJS = require("uglify-js");
Esiste un'unica funzione di alto livello minify(code, options)
, che eseguirà tutte le fasi di minificazione in maniera configurabile, di default minify()
abiliterà le opzioni compress
e mangle
. Esempio:
1
2
3
4var code = "function add(first, second) { return first + second; }";
var result = UglifyJS.minify(code);
console.log(result.error); // runtime error, or `undefined` if no error
console.log(result.code); // minified output: function add(n,d){return n+d}
Puoi minify
più di un file JavaScript alla volta utilizzando un oggetto per il primo argomento in cui le chiavi sono nomi di file e i valori sono il codice sorgente:
1
2
3
4
5
6
7var code = {
"file1.js": "function add(first, second) { return first + second; }",
"file2.js": "console.log(add(1 + 2, 3 + 4));"
};
var result = UglifyJS.minify(code);
console.log(result.code);
// function add(d,n){return d+n}console.log(add(3,7));
L' toplevel
opzione:
1
2
3
4
5
6
7
8var code = {
"file1.js": "function add(first, second) { return first + second; }",
"file2.js": "console.log(add(1 + 2, 3 + 4));"
};
var options = { toplevel: true };
var result = UglifyJS.minify(code, options);
console.log(result.code);
// console.log(3+7);
L' nameCache
opzione:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var options = {
mangle: {
toplevel: true,
},
nameCache: {}
};
var result1 = UglifyJS.minify({
"file1.js": "function add(first, second) { return first + second; }"
}, options);
var result2 = UglifyJS.minify({
"file2.js": "console.log(add(1 + 2, 3 + 4));"
}, options);
console.log(result1.code);
// function n(n,r){return n+r}
console.log(result2.code);
// console.log(n(3,7));
Puoi mantenere la cache dei nomi nel file system nel modo seguente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var cacheFileName = "/tmp/cache.json";
var options = {
mangle: {
properties: true,
},
nameCache: JSON.parse(fs.readFileSync(cacheFileName, "utf8"))
};
fs.writeFileSync("part1.js", UglifyJS.minify({
"file1.js": fs.readFileSync("file1.js", "utf8"),
"file2.js": fs.readFileSync("file2.js", "utf8")
}, options).code, "utf8");
fs.writeFileSync("part2.js", UglifyJS.minify({
"file3.js": fs.readFileSync("file3.js", "utf8"),
"file4.js": fs.readFileSync("file4.js", "utf8")
}, options).code, "utf8");
fs.writeFileSync(cacheFileName, JSON.stringify(options.nameCache), "utf8");
Un esempio di una combinazione di minify()
opzioni:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21var code = {
"file1.js": "function add(first, second) { return first + second; }",
"file2.js": "console.log(add(1 + 2, 3 + 4));"
};
var options = {
toplevel: true,
compress: {
global_defs: {
"@console.log": "alert"
},
passes: 2
},
output: {
beautify: false,
preamble: "/* uglified */"
}
};
var result = UglifyJS.minify(code, options);
console.log(result.code);
// /* uglified */
// alert(10);"
Per produrre avvisi:
1
2
3
4
5
6var code = "function f(){ var u; return 2 + 3; }";
var options = { warnings: true };
var result = UglifyJS.minify(code, options);
console.log(result.error); // runtime error, `undefined` in this case
console.log(result.warnings); // [ 'Dropping unused variable u [0:1,18]' ]
console.log(result.code); // function f(){return 5}
Un esempio di errore:
1
2
3var result = UglifyJS.minify({"foo.js" : "if (0) else console.log(1);"});
console.log(JSON.stringify(result.error));
// {"message":"Unexpected token: keyword (else)","filename":"foo.js","line":1,"col":7,"pos":7}
Nota: a differenza dell'API `uglify-js@2.x, the
3.x` non genera errori. Per ottenere un effetto simile si potrebbe fare quanto segue:
1
2var result = UglifyJS.minify(code, options);
if (result.error) throw result.error;
Minimizza opzioni
warnings
(predefinitofalse
) — passatrue
per restituire gli avvisi del compressore inresult.warnings
. Utilizzare il valore"verbose"
per avvisi più dettagliati.parse
(predefinito{}
) — passa un oggetto se desideri specificare alcune opzioni di analisi aggiuntive .compress
(default{}
) — passafalse
per saltare completamente la compressione Passa un oggetto per specificare le opzioni di compressione personalizzate .mangle
(defaulttrue
) — passafalse
per saltare i nomi di mangling o passa un oggetto per specificare le opzioni di mangle (vedi sotto).mangle.properties
(defaultfalse
) — una sottocategoria dell'opzione mangle Passa un oggetto per specificare le opzioni di proprietà mangle personalizzate .
output
(defaultnull
) — passa un oggetto se desideri specificare ulteriori opzioni di output I valori predefiniti sono ottimizzati per la migliore compressione.sourceMap
(predefinitofalse
)-passa un oggetto se si desidera specificare le opzioni della mappa di origine .toplevel
(predefinitofalse
)-set atrue
se si desidera abilitare la variabile di livello superiore e la modifica del nome della funzione e eliminare le variabili e le funzioni non utilizzate.nameCache
(predefinitonull
)-passa un oggetto vuoto{}
o unnameCache
oggetto usato in precedenza se desideri memorizzare nella cache i nomi di variabili e proprietà alterati attraverso più invocazioni diminify()
. Nota: questa è una proprietà di lettura/scrittura.minify()
leggerà lo stato della cache del nome di questo oggetto e lo aggiornerà durante la minificazione in modo che possa essere riutilizzato o mantenuto esternamente dall'utente.ie8
(predefinitofalse
)-settrue
per supportare IE8.keep_fnames
(predefinito:false
)-passtrue
per impedire l'eliminazione o la manipolazione dei nomi delle funzioni.Utile per il codice che si basa suFunction.prototype.name
.
Minimizza la struttura delle opzioni
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25{
parse: {
// parse options
},
compress: {
// compress options
},
mangle: {
// mangle options
properties: {
// mangle property options
}
},
output: {
// output options
},
sourceMap: {
// source map options
},
nameCache: null, // or specify a name cache object
toplevel: false,
ie8: false,
warnings: false,
}
Source map options
Per generare una mappa di origine:
1
2
3
4
5
6
7
8var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, {
sourceMap: {
filename: "out.js",
url: "out.js.map"
}
});
console.log(result.code); // minified output
console.log(result.map); // source map
Nota che la mappa di origine non viene salvata in un file, viene semplicemente restituita in
result.map
. Il valore passato per sourceMap.url
viene utilizzato solo per impostare
//# sourceMappingURL=out.js.map
in result.code
. Il valore di
filename
viene utilizzato solo per impostare l' file
attributo (vedi le specifiche ) nel file di mappa di origine.
È possibile impostare l'opzione sourceMap.url
su essere "inline"
e la mappa di origine verrà aggiunta al codice.
Puoi anche specificare la proprietà sourceRoot da includere nella mappa di origine:
1
2
3
4
5
6var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, {
sourceMap: {
root: "http://example.com/src",
url: "out.js.map"
}
});
Se stai comprimendo JavaScript compilato e disponi di una mappa di origine, puoi utilizzare sourceMap.content
:
1
2
3
4
5
6
7var result = UglifyJS.minify({"compiled.js": "compiled code"}, {
sourceMap: {
content: "content from compiled.js.map",
url: "minified.js.map"
}
});
// same as before, it returns `code` and `map`
Se invece stai utilizzando l' X-SourceMap
intestazione, puoi semplicemente omettere sourceMap.url
.
Opzioni di analisi
bare_returns
(predefinitofalse
) - supporta lereturn
istruzioni di primo livellohtml5_comments
(predefinitotrue
)shebang
(predefinitotrue
) - supporto#!command
come prima riga
Opzioni di compressione
arguments
(predefinito:)true
- sostituirearguments[index]
con il nome del parametro della funzione quando possibile.booleans
(predefinitotrue
:) - varie ottimizzazioni per il contesto booleano, ad esempio!!a ? b : c → a ? b : c
collapse_vars
(predefinitotrue
:) - Comprimi variabili non costanti monouso, effetti collaterali permettendo.comparisons
(predefinitotrue
:) - applica determinate ottimizzazioni ai nodi binari, ad esempio!(a <= b) → a > b
, tenta di negare i nodi binari, ad esempioa = !b && !c && !d && !e → a=!(b||c||d||e)
ecc.conditionals
(predefinitotrue
:) - applica ottimizzazioni perif
-s ed espressioni condizionalidead_code
(predefinitotrue
:) - rimuove il codice irraggiungibiledrop_console
(predefinito :)false
- Passatrue
a scartare le chiamate alleconsole.*
funzioni. Se desideri eliminare una chiamata di funzione specifica comeconsole.info
e/o conservare gli effetti collaterali dagli argomenti della funzione dopo aver eliminato la chiamata di funzione, usapure_funcs
invece.drop_debugger
(predefinito:)true
- rimuove ledebugger;
istruzionievaluate
(predefinitotrue
:) - tenta di valutare espressioni costantiexpression
(predefinito :)false
- Passatrue
per preservare i valori di completamento dalle istruzioni del terminale senzareturn
, ad esempio nei bookmarklet.global_defs
(predefinito :){}
- vedi compilazione condizionalehoist_funs
(predefinitofalse
:) - dichiarazioni della funzione di sollevamentohoist_props
(predefinitotrue
:) - solleva le proprietà da oggetti costanti e valori letterali dell'array in variabili regolari soggette a una serie di vincoli. Ad esempio:var o={p:1, q:2}; f(o.p, o.q);
viene convertito inf(1, 2);
. Nota:hoist_props
funziona meglio conmangle
abilitato, l'compress
opzionepasses
impostata su2
o superiore e l'compress
opzionetoplevel
abilitata.hoist_vars
(predefinitofalse
:) -var
dichiarazioni di sollevamento (questo èfalse
di default perché sembra aumentare la dimensione dell'output in generale)if_return
(predefinitotrue
:) - ottimizzazioni per if/return e if/continueinline
(predefinitotrue
:) - chiamate in linea per funzionare con semplice/return
istruzione:false
- uguale a0
0
- inline disabilitato1
- funzioni semplici in linea2
- funzioni in linea con argomenti3
- funzioni in linea con argomenti e variabilitrue
- uguale a3
join_vars
(predefinitotrue
:) - uniscivar
istruzioni consecutivekeep_fargs
(predefinitotrue
:) - Impedisce al compressore di scartare gli argomenti della funzione non utilizzati. È necessario questo per il codice che si basa suFunction.length
.keep_fnames
(predefinito :)false
- Passatotrue
per impedire al compressore di scartare i nomi delle funzioni. Utile per il codice che si basa suFunction.prototype.name
. Vedi anche: l'keep_fnames
opzione mangle .keep_infinity
(predefinito :)false
- Passatrue
per evitareInfinity
di essere compresso in1/0
, che potrebbe causare problemi di prestazioni su Chrome.loops
(predefinitotrue
:) - ottimizzazioni perdo
,while
efor
cicli quando possiamo determinare staticamente la condizione.negate_iife
(predefinitotrue
:) - nega "Espressioni di funzione richiamate immediatamente" dove il valore restituito viene scartato, per evitare le parentesi che il generatore di codice inserirebbe.passes
(predefinito:)1
- Il numero massimo di volte per eseguire compress. In alcuni casi più di un passaggio porta a ulteriore codice compresso. Tieni presente che più passaggi richiederanno più tempo.properties
(predefinitotrue
:) - riscrivi l'accesso alla proprietà usando la notazione del punto, ad esempiofoo["bar"] → foo.bar
pure_funcs
(predefinito:)null
- Puoi passare un array di nomi e UglifyJS assumerà che quelle funzioni non producono effetti collaterali. PERICOLO: non controllerà se il nome è ridefinito nell'ambito. Un esempio qui, ad esempiovar q = Math.floor(a/b)
. Se la variabileq
non è usato altrove, UglifyJS lo lascerà cadere, ma manterrà comunque ilMath.floor(a/b)
, non sapendo cosa fa.Puoi passare per farglipure_funcs: [ 'Math.floor' ]
sapere che questa funzione non produrrà alcun effetto collaterale, nel qual caso l'intera istruzione verrebbe scartata.La corrente l'implementazione aggiunge un po' di sovraccarico (la compressione sarà più lenta).Assicurati che anche i simboli sottopure_funcs
siano sottomangle.reserved
per evitare distorsioni.pure_getters
(di default :)"strict"
- Se passatetrue
per questo, UglifyJS si assume che l'accesso alle proprietà oggetto (ad esempio,foo.bar
ofoo["bar"]
) non ha effetti collaterali Specificare."strict"
per trattarefoo.bar
come side-effetto libero solo quandofoo
è certo di non gettare, cioè nonnull
oundefined
.reduce_funcs
(predefinitotrue
:) - Consente alle funzioni monouso di essere incorporate come espressioni di funzione quando consentito consentendo un'ulteriore ottimizzazione. Abilitato per impostazione predefinita. L'opzione dipende dall'abilitazionereduce_vars
. Alcuni codici vengono eseguiti più velocemente nel motore Chrome V8 se questa opzione è disabilitata. Non ha effetti negativi impatto sugli altri principali browser.reduce_vars
(predefinitotrue
:) - Migliora l'ottimizzazione sulle variabili assegnate e utilizzate come valori costanti.sequences
(predefinitotrue
:) - unisci istruzioni semplici consecutive utilizzando l'operatore virgola. Può essere impostato su un numero intero positivo per specificare il numero massimo di sequenze di virgole consecutive che verranno generate. Se questa opzione è impostata su,true
ilsequences
limite predefinito è200
. Imposta l'opzione sufalse
o0
per disabilitare. Lasequences
lunghezza più piccola è2
. Unsequences
valore di1
è considerato equivalente atrue
e come tale significa200
. In rare occasioni il limite di sequenze predefinito porta a tempi di compressione molto lenti, nel qual caso si consiglia un valore20
uguale o inferiore.side_effects
(predefinito :)true
- Passafalse
per disabilitare le funzioni potenzialmente eliminate contrassegnate come "pure". Una chiamata di funzione è contrassegnata come "pura" se un'annotazione di commento/*@__PURE__*/
o/*#__PURE__*/
precede immediatamente la chiamata. Ad esempio:/*@__PURE__*/foo();
switches
(predefinitotrue
:) - deduplica e rimuove iswitch
rami irraggiungibilitoplevel
(predefinitofalse
:) - elimina le funzioni non referenziate ("funcs"
) e/o le variabili ("vars"
) nell'ambito di livello superiore (false
per impostazione predefinita,true
per eliminare sia le funzioni che le variabili non referenziate)top_retain
(predefinitonull
:) - impedisce launused
rimozione di specifiche funzioni e variabili di primo livello (può essere array, separato da virgole, RegExp o funzione. Impliestoplevel
)typeofs
(predefinito:)true
- Si trasformatypeof foo == "undefined"
infoo === void 0
.Nota: consigliamo di impostare questo valorefalse
su IE10 e versioni precedenti a causa di problemi noti.unsafe
(predefinitofalse
:) - applica trasformazioni "non sicure" (discussione sotto)unsafe_comps
(predefinito :)false
- comprime le espressioni comea <= b
supponendo che nessuno degli operandi possa essere (costretto a)NaN
.unsafe_Function
(predefinitofalse
:) - comprime e manipolaFunction(args, code)
quando entrambiargs
ecode
sono letterali stringa.unsafe_math
(predefinitofalse
:) - ottimizza le espressioni numeriche come2 * x * 3
into6 * x
, che possono dare risultati in virgola mobile imprecisi.unsafe_proto
(predefinitofalse
:) - ottimizza le espressioni comeArray.prototype.slice.call(a)
into[].slice.call(a)
unsafe_regexp
(predefinitofalse
:) - abilita le sostituzioni di variabili conRegExp
valori allo stesso modo come se fossero costanti.unsafe_undefined
(predefinitofalse
:) - sostituiscevoid 0
se è presente una variabile denominataundefined
nell'ambito (il nome della variabile verrà alterato, in genere ridotto a un singolo carattere)unused
(predefinitotrue
:) - elimina funzioni e variabili non referenziate (semplici assegnazioni di variabili dirette non contano come riferimenti a meno che non siano impostate su"keep_assign"
)warnings
(predefinitofalse
:) - visualizza avvisi quando si rilascia codice irraggiungibile o dichiarazioni non utilizzate ecc.
Opzioni di stordimento
eval
(defaultfalse
) - Passatrue
ai nomi mangle visibili negli ambiti in cuieval
owith
vengono utilizzati.keep_fnames
(defaultfalse
) - Passatrue
a non manipolare i nomi delle funzioni.Utile per il codice che si basa suFunction.prototype.name
.Vedi anche: l'keep_fnames
opzione compress .reserved
(predefinito[]
) - Passa AN BE dovrebbe Array di identificatori che il mangling è escluso dall'Esempio:.["foo", "bar"]
.toplevel
(defaultfalse
) - Passatrue
ai nomi mangle dichiarati nell'ambito di livello superiore.
Esempi:
1
2
3
4
5// test.js
var globalVar;
function funcName(firstLongName, anotherLongName) {
var myVariable = firstLongName + anotherLongName;
}
1
2
3
4
5
6
7
8
9
10var code = fs.readFileSync("test.js", "utf8");
UglifyJS.minify(code).code;
// 'function funcName(a,n){}var globalVar;'
UglifyJS.minify(code, { mangle: { reserved: ['firstLongName'] } }).code;
// 'function funcName(firstLongName,a){}var globalVar;'
UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
// 'function n(n,a){}var a;'
Mangle properties options
builtins
(predefinito :)false
- Utilizzaretrue
per consentire la manipolazione delle proprietà DOM integrate. Non è consigliabile sovrascrivere questa impostazione.debug
(defaultfalse
:) -- Mangle nomi con il nome originale ancora presente. Passa una stringa vuota""
per abilitare, o una stringa non vuota per impostare il suffisso di debug.keep_quoted
(predefinitofalse
:) -- Modifica solo i nomi di proprietà senza virgolette.regex
(predefinitonull
:) -- Passa un letterale RegExp a mangle solo i nomi di proprietà che corrispondono all'espressione regolare.reserved
(predefinito[]
:) - Non alterare i nomi delle proprietà elencatireserved
nell'array.
Opzioni di uscita
Il generatore di codice cerca di produrre il codice più breve possibile per impostazione predefinita. Nel caso in cui desideri un output abbellito, passa --beautify
( -b
).Opzionalmente puoi passare argomenti aggiuntivi che controllano l'output del codice:
ascii_only
(defaultfalse
) - escape dei caratteri Unicode nelle stringhe e nelle espressioni regolari (influenza le direttive con caratteri non ascii che diventano non validi)beautify
(defaulttrue
) - se abbellire effettivamente l'output.Il passaggio-b
lo imposterà su true, ma potrebbe essere necessario passare-b
anche quando si desidera generare codice minimizzato, al fine di specificare argomenti aggiuntivi, in modo da poterlo utilizzare-b beautify=false
per sovrascriverlo.braces
(impostazione predefinitafalse
) - Sempre in inserire parentesi graffeif
,for
,do
,while
owith
dichiarazioni, il anche il loro corpo è un unico if.comments
(defaultfalse
) - passatrue
o"all"
per preservare tutti i commenti,"some"
per preservare alcuni commenti, una stringa di espressione regolare (es/^!/
) o una funzione.indent_level
(predefinito4
)indent_start
(default0
) - prefissa tutte le righe con quel numero di spaziinline_script
(predefinitotrue
) - escape dei commenti HTML e della barra nelle occorrenze di</script>
in stringhekeep_quoted_props
(predefinitofalse
) - quando attivato, impedisce di eliminare le virgolette dai nomi delle proprietà nei letterali degli oggetti.max_line_len
(predefinitofalse
) - lunghezza massima della riga (per codice non corretto)preamble
(defaultnull
) - quando viene passato deve essere una stringa e verrà anteposto letteralmente all'output. La mappa di origine si adatterà a questo testo. Può essere utilizzato per inserire un commento contenente informazioni sulla licenza, ad esempio.preserve_line
(defaultfalse
) - passtrue
per preservare le righe, ma funziona solo sebeautify
è impostato sufalse
.quote_keys
(predefinitofalse
) - passatrue
per citare tutte le chiavi negli oggetti letteraliquote_style
(default0
) - stile di citazione preferito per le stringhe (influenza anche i nomi di proprietà e le direttive tra virgolette):0
- preferisce le virgolette doppie, passa alle virgolette singole quando ci sono più virgolette nella stringa stessa.0
è la cosa migliore per la dimensione gzip.1
- usa sempre le virgolette singole2
- usa sempre le virgolette doppie3
- usa sempre le virgolette originali
semicolons
(defaulttrue
) - separa le istruzioni con punti e virgola.Se passi,false
quando possibile useremo una nuova riga invece di un punto e virgola, portando a un output più leggibile del codice uglified (la dimensione prima di gzip potrebbe essere più piccola; la dimensione dopo gzip significativamente più grande).shebang
(defaulttrue
) - preserva shebang#!
nel preambolo (script bash)webkit
(impostazione predefinitafalse
) - abilita soluzioni alternative per i bug di WebKit. Gli utenti di PhantomJS dovrebbero impostare questa opzione sutrue
.width
(default80
) - ha effetto solo quando l'abbellimento è attivo, questo specifica una larghezza di linea (orientativa) a cui l'abbellitore proverà a obbedire.Si riferisce alla larghezza del testo della linea (escluso il rientro).Non funziona molto bene attualmente , ma rende più leggibile il codice generato da UglifyJS.wrap_iife
(defaultfalse
) - passatrue
per avvolgere le espressioni di funzione invocate immediatamente.Vedi #640 per maggiori dettagli.
Varie
Keeping copyright notices or other comments
Puoi passare --comments
a conservare determinati commenti nell'output. Per impostazione predefinita manterrà i commenti in stile JSDoc che contengono "@preserve", "@license" o "@cc_on" (compilazione condizionale per IE). Puoi passare
--comments all
a mantenere tutti i commenti o un'espressione regolare JavaScript valida per conservare solo i commenti che corrispondono a questa espressione regolare. Ad esempio --comments /^!/
, manterranno i commenti come /*! Copyright Notice */
.
Tieni presente, tuttavia, che potrebbero verificarsi situazioni in cui i commenti vengono persi, ad esempio:
1
2
3
4
5
6
7function f() {
/** @preserve Foo Bar */
function g() {
// this function is never called
}
return something();
}
Anche se ha "@preserve", il commento andrà perso perché la funzione interna g
(che è il nodo AST a cui è collegato il commento) viene scartata dal compressore come non referenziata.
I commenti più sicuri dove inserire le informazioni sul copyright (o altre informazioni che devono essere mantenute nell'output) sono i commenti allegati ai nodi di primo livello.
L' unsafe
compress
opzione
Abilita alcune trasformazioni che potrebbero infrangere la logica del codice in alcuni casi artificiosi, ma dovrebbe andare bene per la maggior parte del codice. Potresti volerlo provare sul tuo codice, dovrebbe ridurre la dimensione ridotta. Ecco cosa succede quando questo flag è attivo:
new Array(1, 2, 3)
oArray(1, 2, 3)
→[ 1, 2, 3 ]
new Object()
→{}
String(exp)
oexp.toString()
→"" + exp
new Object/RegExp/Function/Error/Array (...)
→ scartiamo ilnew
Conditional compilation
È possibile utilizzare l' opzione --define
( -d
) per dichiarare le variabili globali che UglifyJS assumerà come costanti (a meno che non siano definite nell'ambito) --define DEBUG=false
.Ad esempio, se si passa , insieme alla rimozione del codice morto, UglifyJS scarterà quanto segue dall'output:
1
2
3if (DEBUG) {
console.log("debug stuff");
}
È possibile specificare costanti nidificate sotto forma di --define env.DEBUG=false
.
UglifyJS avviserà che la condizione è sempre falsa e che non viene rilasciato codice irraggiungibile; per ora non è possibile disattivare solo questo avviso specifico, puoi passare warnings=false
a disattivare tutti gli avvisi.
Un altro modo per farlo è dichiarare i tuoi globali come costanti in un file separato e includerli nella build.Ad esempio puoi avere un
build/defines.js
file con quanto segue:
1
2
3var DEBUG = false;
var PRODUCTION = true;
// etc.
e costruisci il tuo codice in questo modo:
1uglifyjs build/defines.js js/foo.js js/bar.js... -c
UglifyJS noterà le costanti e, poiché non possono essere modificate, valuterà i riferimenti ad esse al valore stesso e rilascerà il codice irraggiungibile come al solito. La build conterrà le const
dichiarazioni se le usi. Se stai prendendo di mira ambienti <ES6 che non not support const
, l'utilizzo var
con reduce_vars
(abilitato per impostazione predefinita) dovrebbe essere sufficiente.
Conditional compilation API
Puoi anche utilizzare la compilazione condizionale tramite l'API programmatica, con la differenza che il nome della proprietà è global_defs
ed è una proprietà del compressore:
1
2
3
4
5
6
7
8var result = UglifyJS.minify(fs.readFileSync("input.js", "utf8"), {
compress: {
dead_code: true,
global_defs: {
DEBUG: false
}
}
});
Per sostituire un identificatore con un'espressione arbitraria non costante è necessario anteporre la global_defs
chiave con "@"
per indicare a UglifyJS di analizzare il valore come espressione:
1
2
3
4
5
6
7
8UglifyJS.minify("alert('hello');", {
compress: {
global_defs: {
"@alert": "console.log"
}
}
}).code;
// returns: 'console.log("hello");'
Altrimenti verrebbe sostituito come stringa letterale:
1
2
3
4
5
6
7
8UglifyJS.minify("alert('hello');", {
compress: {
global_defs: {
"alert": "console.log"
}
}
}).code;
// returns: '"console.log"("hello");'
Utilizzo di Uglify AST nativo con minify()
1
2
3
4
5
6
7
8
9
10
11
12
13// example: parse only, produce native Uglify AST
var result = UglifyJS.minify(code, {
parse: {},
compress: false,
mangle: false,
output: {
ast: true,
code: false // optional - faster if false
}
});
// result.ast contains native Uglify AST
1
2
3
4
5
6
7
8
9
10
11
12
13
14// example: accept native Uglify AST input and then compress and mangle
// to produce both code and native AST.
var result = UglifyJS.minify(ast, {
compress: {},
mangle: {},
output: {
ast: true,
code: true // optional - faster if false
}
});
// result.ast contains native Uglify AST
// result.code contains the minified code in string form.
Working with Uglify AST
Trasversale e trasformazione dell'AST nativo possono essere eseguite
rispettivamente tramite
TreeWalker
e
TreeTransformer
.
ESTree / SpiderMonkey AST
UglifyJS ha un proprio formato astratto dell'albero della sintassi, per ragioni pratiche non possiamo passare facilmente all'uso interno di SpiderMonkey AST, tuttavia, ora UglifyJS ha un convertitore che può importare un SpiderMonkey AST.
Ad esempio Acorn è un parser super veloce che produce un SpiderMonkey AST.Ha una piccola utility CLI che analizza un file e scarica l'AST in JSON sull'output standard.Per usare UglifyJS per manipolare e comprimerlo:
1acorn file.js | uglifyjs -p spidermonkey -m -c
L' -p spidermonkey
opzione dice a UglifyJS che tutti i file di input non sono JavaScript, ma il codice JS descritto in SpiderMonkey AST in JSON.Quindi non usiamo il nostro parser in questo caso, ma semplicemente trasformiamo quell'AST nel nostro AST interno.
Use Acorn for parsing
Più per divertimento, ho aggiunto l' -p acorn
opzione che utilizzerà Acorn per eseguire tutte le analisi.Se passi questa opzione, UglifyJS lo farà require("acorn")
.
Acorn è molto veloce (es. 250 ms invece di 380 ms su un codice da 650 K), ma la conversione dell'albero SpiderMonkey che produce Acorn richiede altri 150 ms, quindi in totale è un po' più che usare il parser di UglifyJS.
Uglify Fast Minify Mode
Non è ben noto, ma la rimozione degli spazi bianchi e la manipolazione dei simboli rappresentano il 95% di a La riduzione delle dimensioni del codice minimizzato per la maggior parte dei JavaScript - Non elaborare il codice TRANSFORMS Si può semplicemente disabilitare compress
per velocizzare le build di Uglify da 3 a 4 volte nel questo è il VELOCE mangle
- solo la modalità Uglify ha velocità di minimizzazione e dimensioni gzip comparabili a
butternut
:
d3.js | minimizzare le dimensioni | dimensione gzip | tempo di minimizzazione (secondi) |
---|---|---|---|
originale | 451.131 | 108.733 | - |
uglify-js@3.0.24 mangle=false, compress=false | 316,600 | 85.245 | 0.70 |
uglify-js@3.0.24 mangle=true, compress=false | 220,216 | 72,730 | 1.13 |
butternut@0.4.6 | 217.568 | 72.738 | 1.41 |
uglify-js@3.0.24 mangle=true, compress=true | 212.511 | 71.560 | 3.36 |
babili@0.1.4 | 210.713 | 72,140 | 12.64 |
Per abilitare la modalità di minimizzazione rapida dalla CLI, utilizzare:
1uglifyjs file.js -m
Per abilitare la modalità di minimizzazione rapida con l'utilizzo dell'API:
1UglifyJS.minify(code, { compress: false, mangle: true });
Mappe sorgente e debug
compress
È noto che varie trasformazioni che semplificano, riorganizzano, incorporano e rimuovono il codice hanno un effetto negativo sul debug con le mappe di origine. Ciò è previsto poiché il codice è ottimizzato e le mappature spesso non sono semplicemente possibili poiché parte del codice non esiste più. Per la massima fedeltà nel codice sorgente il debug della mappa disabilita l' compress
opzione Uglify e usa semplicemente mangle
.
Compiler assumptions
Per consentire migliori ottimizzazioni, il compilatore fa varie ipotesi:
.toString()
e.valueOf()
non hanno effetti collaterali e per gli oggetti incorporati non sono stati sovrascritti.undefined
,NaN
eInfinity
non sono stati ridefiniti esternamente.arguments.callee
,arguments.caller
eFunction.prototype.caller
non vengono utilizzati.- Il codice non si aspetta che il contenuto
Function.prototype.toString()
oError.prototype.stack
che sia qualcosa in particolare. - Ottenere e impostare proprietà su un oggetto semplice non causa altri effetti collaterali (usando
.watch()
oProxy
). - PU ESSERE aggiunto l'Oggetto Proprietà, rimosso e Modificato (non impedito con
Object.defineProperty()
,Object.defineProperties()
,Object.freeze()
,Object.preventExtensions()
oObject.seal()
).