UglifyJS 3
UglifyJS è un toolkit per parser, minimizzazione, compressione e abbellimento JavaScript.
Nota:
uglify-js@3
ha un'API e una CLI semplificate che non sono retrocompatibili conuglify-js@2
.- La documentazione per
2.x
le versioni UglifyJS può essere trovata qui . uglify-js
supporta solo JavaScript (ECMAScript 5).- Per minimizzare ECMAScript 2015 o versioni successive, esegui la transpilazione utilizzando strumenti come Babel .
Installare
Per prima cosa assicurati di aver installato la versione più recente di node.js (potresti dover 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 passare le opzioni. UglifyJS analizzerà i file di input in sequenza e applicherà eventuali 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 opzioni prima dei file di input, separa i due con un doppio trattino per evitare che i file di input vengano utilizzati come argomenti di 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 della mappa sorgente CLI
UglifyJS può generare un file di mappa sorgente, che è molto utile per eseguire il debug del tuo JavaScript compresso. Per ottenere una mappa sorgente, passa
--source-map --output output.js
(la mappa sorgente 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 sorgente. Altrimenti UglifyJS presuppone 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 manipolerà file1.js
e file2.js
, trascinerà l'output in foo.min.js
e la mappa sorgente in foo.min.js.map
. La mappatura sorgente farà riferimento a http://foo.com/src/js/file1.js
e
http://foo.com/src/js/file2.js
(in effetti elencherà http://foo.com/src
come radice della mappa sorgente e i file originali come js/file1.js
e
js/file2.js
).
Composed source map
Quando comprimi il codice JS generato da un compilatore come CoffeeScript, la mappatura al codice JS non sarà molto utile. Ti piacerebbe invece mappare nuovamente al codice originale (ad esempio CoffeeScript). 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à passare --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
È necessario passare --compress
( ) per abilitare il compressore. Facoltativamente è possibile passare un elenco di opzioni di compressione-c
separate da virgole .
Le opzioni sono nella forma foo=bar
, o semplicemente foo
(quest'ultima implica un'opzione booleana che desideri impostare true
; è effettivamente una scorciatoia per foo=true
).
Esempio:
1uglifyjs file.js -c toplevel,sequences=false
Opzioni di modifica della CLI
Per abilitare il manipolatore è necessario passare --mangle
( -m
). Sono supportate le seguenti opzioni (separate da virgole):
toplevel
(defaultfalse
) -- modifica i nomi dichiarati nell'ambito del livello superiore.eval
(impostazione predefinitafalse
) -- modifica i nomi visibili negli ambiti in cui vengono utilizzatieval
o .with
Quando la modifica è abilitata ma vuoi evitare che determinati nomi vengano modificati, puoi dichiararli con --mangle reserved
— passa un elenco di nomi separati da virgole. Ad esempio:
1uglifyjs ... -m reserved=['$','require','exports']
per evitare che i nomi require
, exports
e $
vengano modificati.
Nomi delle proprietà di modifica della CLI ( --mangle-props
)
Nota: QUESTO PROBABILMENTE ROMPERÀ IL TUO CODICE. La modifica dei nomi delle proprietà è un passaggio separato, diverso dalla modifica dei nomi delle variabili. Passa
--mangle-props
per abilitarlo. Manipolerà tutte le proprietà nel codice di input ad eccezione delle proprietà DOM integrate e delle proprietà nel JavaScript principale 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à (tranne 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._());
Modifica tutte le proprietà corrispondenti 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à di mangle:
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
per sovrascrivere).
Viene fornito un file di esclusione predefinito tools/domprops.json
che dovrebbe coprire la maggior parte delle proprietà JS e DOM standard definite in vari browser. Passa
--mangle-props domprops
per disabilitare questa funzione.
È possibile utilizzare un'espressione regolare per definire quali nomi di proprietà devono essere modificati. Ad esempio, --mangle-props regex=/^_/
modificherà solo i nomi di proprietà che iniziano con un carattere di sottolineatura.
Quando comprimi più file utilizzando questa opzione, affinché possano lavorare insieme alla fine dobbiamo assicurarci in qualche modo che una proprietà venga modificata con lo stesso nome in tutti. Per questo, passa --name-cache filename.json
e UglifyJS manterrà queste mappature in un file che potrà poi 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 file in un'unica chiamata a UglifyJS.
Mutilazione di nomi senza virgolette ( --mangle-props keep_quoted
)
L'uso 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 modificare i nomi delle proprietà senza oscurarli completamente. Ad esempio, la proprietà o.foo
potrebbe essere modificata o._$foo$_
con questa opzione. Ciò consente la modifica delle proprietà di una base di codice di grandi dimensioni pur essendo in grado di eseguire il debug del codice e identificare dove la manipolazione sta danneggiando 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 utilizzando --mangle-props debug=XYZ
. Questo verrebbe poi modificato o.foo
in o._$foo$XYZ_
. Puoi cambiarlo ogni volta che compili uno script per identificare come una proprietà è stata modificata. Una tecnica è passare un numero casuale su ogni compilazione per simulare la modifica del suffisso 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 minimizzazione in modo 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 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 rendere persistente 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 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 di uglify-js@2.x
, l' 3.x
API 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 le opzioni
warnings
(impostazione predefinitafalse
) - passatrue
per restituire gli avvisi del compressore inresult.warnings
Utilizzare il valore"verbose"
per avvisi più dettagliati.parse
(impostazione predefinita{}
) — passa un oggetto se desideri specificare alcune opzioni di analisi aggiuntive .compress
(impostazione predefinita{}
): passafalse
per ignorare completamente la compressione. Passa un oggetto per specificare le opzioni di compressione personalizzate .mangle
(defaulttrue
) — passafalse
per saltare la modifica dei nomi o passa un oggetto per specificare le opzioni di modifica (vedi sotto).mangle.properties
(defaultfalse
) — una sottocategoria dell'opzione mangle. Passa un oggetto per specificare le opzioni personalizzate della proprietà mangle .
output
(impostazione predefinitanull
): passa un oggetto se desideri specificare opzioni di output aggiuntive . Le impostazioni predefinite sono ottimizzate per la migliore compressione.sourceMap
(impostazione predefinitafalse
) - passa un oggetto se desideri specificare le opzioni della mappa sorgente .toplevel
(impostazione predefinitafalse
) - impostare sutrue
se si desidera abilitare la modifica dei nomi delle variabili e delle funzioni di livello superiore e eliminare le variabili e le funzioni inutilizzate.nameCache
(impostazione predefinitanull
) - passa un oggetto vuoto{}
o un oggetto utilizzato in precedenzanameCache
se desideri memorizzare nella cache nomi di variabili e proprietà alterate attraverso più invocazioni diminify()
. Nota: questa è una proprietà di lettura/scrittura.minify()
leggerà lo stato della cache dei nomi di questo oggetto e lo aggiornerà durante la minimizzazione in modo che possa essere riutilizzato o reso persistente esternamente dall'utente.ie8
(impostazione predefinitafalse
) - impostato pertrue
supportare IE8.keep_fnames
(default:false
) - passaggiotrue
per evitare di scartare o alterare i 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
Tieni presente 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 file
l'attributo (vedere le specifiche ) nel file di mappa di origine.
È possibile impostare l'opzione sourceMap.url
su be "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 sorgente, 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 utilizzi l' X-SourceMap
intestazione, puoi semplicemente omettere sourceMap.url
.
Opzioni di analisi
bare_returns
(impostazione predefinitafalse
) - supportareturn
le dichiarazioni di livello superiorehtml5_comments
(predefinitotrue
)shebang
(impostazione predefinitatrue
) - supporto#!command
come prima riga
Opzioni di compressione
arguments
(impostazione predefinita:true
) -- sostituirearguments[index]
con il nome del parametro della funzione quando possibile.booleans
(default:true
) -- varie ottimizzazioni per il contesto booleano, ad esempio!!a ? b : c → a ? b : c
collapse_vars
(impostazione predefinita:true
) -- Comprime le variabili non costanti monouso, effetti collaterali permettendo.comparisons
(impostazione predefinita:true
) -- 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
(impostazione predefinita:true
) -- applica ottimizzazioni perif
-s ed espressioni condizionalidead_code
(impostazione predefinita:true
) -- rimuove il codice irraggiungibiledrop_console
(impostazione predefinita:false
) -- Passatrue
per scartare le chiamate alleconsole.*
funzioni.Se desideri eliminare una chiamata di funzione specifica comeconsole.info
e/o conservare gli effetti collaterali degli argomenti della funzione dopo aver eliminato la chiamata di funzione, utilizzapure_funcs
invece.drop_debugger
(impostazione predefinita:true
) -- rimuovedebugger;
le istruzionievaluate
(default:true
) -- tenta di valutare espressioni costantiexpression
(impostazione predefinita:false
) -- Passatrue
per preservare i valori di completamento dalle istruzioni terminali senzareturn
, ad esempio nei bookmarklet.global_defs
(default:{}
) -- vedi compilazione condizionalehoist_funs
(default:false
) -- dichiarazioni della funzione di sollevamentohoist_props
(impostazione predefinita:true
) -- proprietà di sollevamento da oggetti costanti e valori letterali di 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
(default:false
) --var
dichiarazioni di sollevamento (questo èfalse
per default perché sembra aumentare la dimensione dell'output in generale)if_return
(impostazione predefinita:true
) -- ottimizzazioni per if/return e if/continueinline
(impostazione predefinita:true
) -- chiamate in linea alla funzione conreturn
l'istruzione semplice/:false
--uguale a0
0
-- Incorporamento disabilitato1
-- Funzioni semplici in linea2
-- funzioni inline con argomenti3
-- funzioni inline con argomenti e variabilitrue
--uguale a3
join_vars
(impostazione predefinita:true
) -- uniscevar
istruzioni consecutivekeep_fargs
(impostazione predefinita:true
) -- Impedisce al compressore di scartare gli argomenti della funzione inutilizzati. È necessario per il codice che si basa suFunction.length
.keep_fnames
(default:false
) -- Passatrue
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
(impostazione predefinita:false
) - Passatrue
per evitareInfinity
che venga compresso in1/0
, il che potrebbe causare problemi di prestazioni su Chrome.loops
(impostazione predefinita:true
) -- ottimizzazioni perdo
,while
efor
cicli quando possiamo determinare staticamente la condizione.negate_iife
(impostazione predefinita:true
) -- nega le "espressioni di funzioni immediatamente chiamate" dove il valore restituito viene scartato, per evitare le parentesi che il generatore di codice inserirà.passes
(impostazione predefinita:1
) - Il numero massimo di volte per eseguire la compressione. In alcuni casi più di un passaggio porta a un ulteriore codice compresso. Tieni presente che più passaggi richiederanno più tempo.properties
(impostazione predefinita:true
) -- riscrive l'accesso alle proprietà utilizzando la notazione punto, ad esempiofoo["bar"] → foo.bar
pure_funcs
(impostazione predefinita:null
) -- Puoi passare un array di nomi e UglifyJS presumerà che tali funzioni non producano effetti collaterali. PERICOLO: non controllerà se il nome è ridefinito nell'ambito. Un caso di esempio qui, ad esempio.var q = Math.floor(a/b)
Se la variabileq
è non utilizzato altrove, UglifyJS lo eliminerà, ma manterrà comunque ilMath.floor(a/b)
, non sapendo cosa fa. Puoi passarepure_funcs: [ 'Math.floor' ]
per fargli sapere che questa funzione non produrrà alcun effetto collaterale, nel qual caso l'intera istruzione verrebbe scartata. l'attuale implementazione aggiunge un po' di sovraccarico (la compressione sarà più lenta). Assicurati che i simboli sottopure_funcs
siano anche sottomangle.reserved
per evitare alterazioni.pure_getters
(impostazione predefinita:"strict"
) -- Se passitrue
per questo, UglifyJS presuppone che l'accesso alle proprietà dell'oggetto (ad esempiofoo.bar
ofoo["bar"]
) non abbia effetti collaterali. Specifica"strict"
di trattarefoo.bar
come privo di effetti collaterali solo quandofoo
è sicuro di non lanciare, cioè nonnull
Oundefined
.reduce_funcs
(impostazione predefinita:true
) - Consente di incorporare funzioni monouso come espressioni di funzioni quando consentito consentendo un'ulteriore ottimizzazione. Abilitato per impostazione predefinita. L'opzione dipendereduce_vars
dall'abilitazione. Alcuni codici vengono eseguiti più velocemente nel motore Chrome V8 se questa opzione è disabilitata. Non funziona avere un impatto negativo sugli altri principali browser.reduce_vars
(impostazione predefinita:true
) -- Migliora l'ottimizzazione delle variabili assegnate e utilizzate come valori costanti.sequences
(impostazione predefinita:true
) -- unisce 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 opzione afalse
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 caso20
si consiglia un valore pari o inferiore.side_effects
(impostazione predefinita: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
(impostazione predefinita:true
) -- deduplica e rimuoveswitch
i rami non raggiungibilitoplevel
(impostazione predefinita:false
) -- rilascia funzioni senza riferimenti ("funcs"
) e/o variabili ("vars"
) nell'ambito di livello superiore (false
per impostazione predefinita,true
per eliminare sia le funzioni che le variabili senza riferimenti)top_retain
(impostazione predefinita:null
) -- impedisceunused
la rimozione di funzioni e variabili di livello superiore specifiche (può essere un array, separato da virgole, RegExp o una funzione. Implicatoplevel
)typeofs
(impostazione predefinita:true
) - Si trasformatypeof foo == "undefined"
infoo === void 0
.Nota: si consiglia di impostare questo valore sufalse
per IE10 e versioni precedenti a causa di problemi noti.unsafe
(impostazione predefinita:false
) -- applica trasformazioni "non sicure" (discussione sotto)unsafe_comps
(default:false
) -- comprime le espressioni come sea <= b
si presupponesse che nessuno degli operandi possa essere (costringuto a)NaN
.unsafe_Function
(impostazione predefinita:false
) -- comprime e alteraFunction(args, code)
quando entrambiargs
ecode
sono stringhe letterali.unsafe_math
(impostazione predefinita:false
) -- ottimizza le espressioni numeriche come2 * x * 3
into6 * x
, che potrebbero fornire risultati in virgola mobile imprecisi.unsafe_proto
(impostazione predefinita:false
) -- ottimizza le espressioni comeArray.prototype.slice.call(a)
into[].slice.call(a)
unsafe_regexp
(impostazione predefinita:false
) - abilita la sostituzione delle variabili conRegExp
valori come se fossero costanti.unsafe_undefined
(impostazione predefinita:false
) -- sostituiscevoid 0
se è presente una variabile denominataundefined
nell'ambito (il nome della variabile verrà alterato, in genere ridotto a un singolo carattere)unused
(impostazione predefinita:true
) -- elimina funzioni e variabili senza riferimenti (le semplici assegnazioni di variabili dirette non contano come riferimenti a meno che non siano impostate su"keep_assign"
)warnings
(impostazione predefinita:false
) -- visualizza avvisi quando si rilascia codice irraggiungibile o dichiarazioni non utilizzate, ecc.
Opzioni di trasformazione
eval
(impostazione predefinitafalse
) -- Passatrue
per modificare i nomi visibili negli ambiti in cui vengono utilizzatieval
o .with
keep_fnames
(defaultfalse
) -- Passatrue
per non modificare i nomi delle funzioni. Utile per il codice che si basa suFunction.prototype.name
. Vedi anche: l'keep_fnames
opzione compress .reserved
(default[]
) -- Passa un array di identificatori che dovrebbero essere esclusi dalla modifica. Esempio:["foo", "bar"]
.toplevel
(defaultfalse
) -- Passatrue
a modificare i nomi 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
(impostazione predefinita:false
) -- Da utilizzaretrue
per consentire la modifica delle proprietà DOM integrate. Non è consigliabile sovrascrivere questa impostazione.debug
(impostazione predefinita:false
) -- Modifica i 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
(impostazione predefinita:false
) -- Modifica solo i nomi di proprietà senza virgolette.regex
(impostazione predefinita:null
) -- Passa un valore letterale RegExp per modificare solo i nomi delle proprietà che corrispondono all'espressione regolare.reserved
(impostazione predefinita:[]
) -- Non altera i nomi delle proprietà elencate nell'arrayreserved
.
Opzioni di uscita
Per impostazione predefinita, il generatore di codice tenta di generare il codice più breve possibile. Nel caso in cui desideri un output abbellito, passa --beautify
( -b
). Facoltativamente puoi passare argomenti aggiuntivi che controllano l'output del codice:
ascii_only
(defaultfalse
) -- escape caratteri Unicode in stringhe ed espressioni regolari (influenza le direttive con caratteri non-ascii che diventano non validi)beautify
(impostazione predefinitatrue
) - 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, per specificare argomenti aggiuntivi, in modo da poterlo utilizzare-b beautify=false
per sovrascriverlo.braces
(impostazione predefinitafalse
) -- inserisce sempre le parentesi graffe nelle istruzioniif
,for
, o , anche sedo
il loro corpo è una singola istruzione.while
with
comments
(defaultfalse
) -- passatrue
o"all"
per preservare tutti i commenti,"some"
per preservare alcuni commenti, una stringa di espressione regolare (ad esempio/^!/
) o una funzione.indent_level
(predefinito4
)indent_start
(default0
) -- prefisso tutte le righe con quel numero di spaziinline_script
(impostazione predefinitatrue
) -- evita i commenti HTML e la barra nelle occorrenze di</script>
stringhekeep_quoted_props
(impostazione predefinitafalse
) -- se attivato, impedisce di rimuovere le virgolette dai nomi delle proprietà nei valori letterali degli oggetti.max_line_len
(defaultfalse
) -- lunghezza massima della riga (per codice brutto)preamble
(defaultnull
) -- quando passato deve essere una stringa e verrà anteposto letteralmente all'output. La mappa sorgente si adatterà a questo testo. Può essere utilizzato per inserire un commento contenente informazioni sulla licenza, ad esempio.preserve_line
(impostazione predefinitafalse
) - passatrue
per preservare le righe, ma funziona solo sebeautify
è impostato sufalse
.quote_keys
(defaultfalse
) -- passatrue
per virgolette tutte le chiavi negli oggetti letteraliquote_style
(default0
) -- stile di virgolette preferito per le stringhe (influenza anche i nomi delle proprietà e le direttive tra virgolette):0
-- preferisce le virgolette doppie, passa alle virgolette singole quando ci sono più virgolette doppie nella stringa stessa.0
È meglio per le dimensioni di gzip.1
-- usa sempre virgolette singole2
-- usa sempre le virgolette doppie3
-- usa sempre le virgolette originali
semicolons
(defaulttrue
) -- separa le istruzioni con punto e virgola. Se lo passi,false
quando possibile utilizzeremo un ritorno a capo invece del punto e virgola, portando a un output più leggibile del codice brutto (la dimensione prima di gzip potrebbe essere più piccola; la dimensione dopo gzip leggermente più grande).shebang
(impostazione predefinitatrue
) -- preserva shebang#!
nel preambolo (script bash)webkit
(impostazione predefinitafalse
) - abilita soluzioni alternative per i bug di WebKit. Gli utenti PhantomJS dovrebbero impostare questa opzione sutrue
.width
(impostazione predefinita80
) - ha effetto solo quando l'abbellimento è attivo, specifica una larghezza di linea (orientativa) a cui l'abbellitore cercherà di obbedire. Si riferisce alla larghezza del testo della riga (escluso il rientro). Non funziona molto bene attualmente, ma rende il codice generato da UglifyJS più leggibile.wrap_iife
(defaultfalse
) -- passatrue
per racchiudere le espressioni di funzioni immediatamente invocate. Vedi #640 per maggiori dettagli.
Varie
Keeping copyright notices or other comments
Puoi passare --comments
per 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
per mantenere tutti i commenti commenti o un'espressione regolare JavaScript valida per conservare solo i commenti che corrispondono a questa espressione regolare. Ad esempio, --comments /^!/
manterrà 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 contiene "@preserve", il commento andrà perso perché la funzione interna g
(che è il nodo AST a cui è allegato il commento) viene scartata dal compressore perché non referenziata.
I commenti più sicuri in cui inserire le informazioni sul copyright (o altre informazioni che devono essere conservate nell'output) sono i commenti allegati ai nodi di livello superiore.
L' unsafe
compress
opzione
Abilita alcune trasformazioni che potrebbero interrompere la logica del codice in alcuni casi inventati, ma dovrebbe andare bene per la maggior parte del codice. Potresti provarlo sul tuo codice, dovrebbe ridurre la dimensione ridotta. Ecco cosa succede quando questo flag è attivo:
new Array(1, 2, 3)
oppureArray(1, 2, 3)
→[ 1, 2, 3 ]
new Object()
→{}
String(exp)
oppureexp.toString()
→"" + exp
new Object/RegExp/Function/Error/Array (...)
→ scartiamo ilnew
Conditional compilation
Puoi utilizzare l' opzione --define
( -d
) per dichiarare variabili globali che UglifyJS assumerà come costanti (a meno che non siano definite nell'ambito). Ad esempio, se lo passi --define DEBUG=false
, insieme alla rimozione del codice morto, UglifyJS scarterà quanto segue dall'output:
1
2
3if (DEBUG) {
console.log("debug stuff");
}
È possibile specificare costanti nidificate nel formato --define env.DEBUG=false
.
UglifyJS avviserà del fatto che la condizione è sempre falsa e dell'eliminazione di codice irraggiungibile; per ora non esiste un'opzione per disattivare solo questo avviso specifico, puoi passare warnings=false
a disattivare tutti gli avvisi.
Un altro modo per farlo è dichiarare i valori 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 in base 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 alla global_defs
chiave il prefisso "@"
per indicare a UglifyJS di analizzare il valore come un'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");'
Utilizzando Uglify AST nativo conminify()
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
La trasversale e la trasformazione dell'AST nativo possono essere eseguite tramite
TreeWalker
e
TreeTransformer
rispettivamente.
ESTree / SpiderMonkey AST
UglifyJS ha un proprio formato di albero della sintassi astratto; per ragioni pratiche non possiamo passare facilmente all'utilizzo di SpiderMonkey AST internamente. Tuttavia, UglifyJS ora ha un convertitore che può importare un SpiderMonkey AST.
Ad esempio Acorn è un parser super veloce che produce un AST SpiderMonkey. Ha una piccola utility CLI che analizza un file e scarica l'AST in JSON sull'output standard. Per utilizzare UglifyJS per manipolarlo 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 codice JS descritto in SpiderMonkey AST in JSON. Pertanto in questo caso non utilizziamo il nostro parser, ma trasformiamo semplicemente quell'AST nel nostro AST interno.
Use Acorn for parsing
Più per divertimento, ho aggiunto l' -p acorn
opzione che utilizzerà Acorn per eseguire tutta l'analisi. Se passi questa opzione, UglifyJS lo farà require("acorn")
.
Acorn è davvero veloce (ad esempio 250 ms invece di 380 ms su un codice da 650 KB), ma la conversione dell'albero SpiderMonkey prodotto da Acorn richiede altri 150 ms, quindi in totale è un po' di più del semplice utilizzo del parser di UglifyJS.
Uglify Fast Minify Mode
Non è molto noto, ma la rimozione degli spazi bianchi e la modifica dei simboli rappresentano il 95% della riduzione delle dimensioni del codice minimizzato per la maggior parte dei JavaScript, non per trasformazioni di codice elaborate. È possibile semplicemente disabilitarle compress
per accelerare le build di Uglify di 3 o 4 volte. In questo modo veloce mangle
: l'unica modalità Uglify ha velocità di minimizzazione e dimensioni gzip paragonabili a
butternut
:
d3.js | minimizzare le dimensioni | dimensione del gzip | minimizzare il tempo (secondi) |
---|---|---|---|
originale | 451.131 | 108.733 | - |
uglify-js@3.0.24 mangle=falso, compress=falso | 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 di origine e debug
È noto che varie compress
trasformazioni che semplificano, riorganizzano, incorporano e rimuovono il codice hanno un effetto negativo sul debugging con le mappe di origine. Ciò è previsto poiché il codice è ottimizzato e le mappature spesso semplicemente non sono possibili poiché parte del codice non esiste più. il debug della mappa disabilita l' compress
opzione Uglify e usa semplicemente mangle
.
Compiler assumptions
Per consentire ottimizzazioni migliori, il compilatore fa varie ipotesi:
.toString()
e.valueOf()
non hanno effetti collaterali e per gli oggetti incorporati non sono stati sovrascritti.undefined
eNaN
nonInfinity
sono stati ridefiniti esternamente.arguments.callee
earguments.caller
nonFunction.prototype.caller
vengono utilizzati.- Il codice non prevede che il contenuto
Function.prototype.toString()
oError.prototype.stack
sia qualcosa in particolare. - Ottenere e impostare proprietà su un oggetto semplice non causa altri effetti collaterali (usando
.watch()
oProxy
). - Le proprietà dell'oggetto possono essere aggiunte
, rimosse e modificate (non impedite con
Object.defineProperty()
,Object.defineProperties()
, o ).Object.freeze()
Object.preventExtensions()
Object.seal()