Fantastico modulo della community

UglifyJS 3

UglifyJS è un toolkit per parser, minifier, compressore e abbellimento JavaScript.

Nota:

  • uglify-js@3 ha un'API e una CLI semplificate che non sono retrocompatibili con uglify-js@2 .
  • La documentazione per le versioni di UglifyJS 2.x può essere trovata qui .
  • uglify-js supporta solo JavaScript (ECMAScript 5).
  • To minify ECMAScript 2015 or above , traspila utilizzando strumenti come Babel .

Installare

Per prima cosa 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 della riga di comando:

1
npm install uglify-js -g

Da NPM per uso programmatico:

1
npm install uglify-js

Utilizzo della riga di comando

1
uglifyjs [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à le opzioni di compressione. I file vengono analizzati nello stesso ambito globale, ovvero un riferimento da un file a qualche variabile / funzione dichiarata in un altro file verrà abbinato 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 i due con un doppio trattino per evitare che i file di input vengano usati come argomenti delle opzioni:

1
uglifyjs --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 il debug del JavaScript compresso. Per ottenere una mappa di origine, passare --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 che venga utilizzato HTTP X-SourceMap la //# sourceMappingURL= direttiva.

Per esempio:

1 2 3
uglifyjs 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 file1.js e file2.js , lascerà cadere 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 (infatti elencherà http://foo.com/src come root della mappa sorgente e i file originali come js/file1.js e js/file2.js ).

Composed source map

Quando comprimi il codice JS che è stato emesso da un compilatore come CoffeeScript, la mappatura al codice JS non sarà troppo utile. Invece, ti piacerebbe mappare di nuovo al codice originale (cioè CoffeeScript). UglifyJS ha un 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 alla sua posizione originale.

Per utilizzare questa funzione, passa --source-map "content='/path/to/input/source.map'" o --source-map "content=inline" se la mappa di origine è inclusa in linea con le fonti.

Opzioni di compressione CLI

Devi passare --compress ( -c ) per abilitare il compressore. Opzionalmente 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 a true ; è effettivamente una scorciatoia per foo=true ).

Esempio:

1
uglifyjs file.js -c toplevel,sequences=false

Opzioni di manipolazione della CLI

Per abilitare il mangler devi passare --mangle ( -m ). Sono supportate le seguenti opzioni (separate da virgole):

  • toplevel (default false ) - nomi mangle dichiarati nell'ambito di primo livello.

  • eval (valore predefinito false ) - mangle nomi visibili negli ambiti in cui vengono utilizzati eval o with .

Quando la manipolazione è abilitata ma si desidera impedire che determinati nomi vengano alterati, è possibile dichiarare quei nomi con --mangle reserved - passare un elenco di nomi separati da virgole. Ad esempio:

1
uglifyjs ... -m reserved=['$','require','exports']

per evitare che la require , le exports e $ nomi $ vengano modificati.

Nomi proprietà --mangle-props CLI ( --mangle-props )

Nota: QUESTO POTREBBE INTERROMPERE IL TUO CODICE. La manipolazione dei nomi delle proprietà è un passaggio separato, diverso dalla modifica del nome della variabile. Passa --mangle-props per abilitarlo. Mangerà tutte le proprietà nel codice di input ad eccezione delle proprietà DOM integrate e proprietà nelle classi JavaScript principali. 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à (ad eccezione dei builtins JavaScript):

1
$ uglifyjs example.js -c -m --mangle-props
1
var x={o:0,_:1,l:function(){return this._+this.o}};x.t=2,x.o=3,console.log(x.l());

Mangia tutte le proprietà ad eccezione di quelle reserved :

1
$ uglifyjs example.js -c -m --mangle-props reserved=[foo_,bar_]
1
var x={o:0,foo_:1,_:function(){return this.foo_+this.o}};x.bar_=2,x.o=3,console.log(x._());

Mangia tutte le proprietà che corrispondono a regex :

1
$ uglifyjs example.js -c -m --mangle-props regex=/_$/
1
var x={o:0,_:1,calc:function(){return this._+this.o}};x.l=2,x.o=3,console.log(x.calc());

Combinazione di opzioni di proprietà mangle:

1
$ uglifyjs example.js -c -m --mangle-props regex=/_$/,reserved=[bar_]
1
var x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log(x.calc());

Affinché ciò sia di qualsiasi utilità, evitiamo di alterare i nomi JS standard per impostazione predefinita ( --mangle-props builtins da sovrascrivere).

Un file di esclusione predefinito è fornito in tools/domprops.json che dovrebbe coprire la maggior parte delle proprietà JS e DOM standard definite in vari --mangle-props domprops per disabilitare questa funzione.

Un'espressione regolare può essere utilizzata per definire quali nomi di proprietà devono essere alterati.Ad esempio, --mangle-props regex=/^_/ manterrà solo i nomi di proprietà che iniziano con un trattino basso.

Quando comprimi più file usando questa opzione, affinché alla fine funzionino insieme dobbiamo assicurarci che una proprietà venga alterata con lo stesso nome in tutti loro. Per questo, passa --name-cache filename.json 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'utilizzo della cache dei nomi non è necessario se comprimi tutti i file in una singola chiamata a UglifyJS.

Mangiare nomi non quotati ( --mangle-props keep_quoted )

Usando il nome della proprietà tra virgolette ( o["foo"] ) si riserva il nome della proprietà ( foo ) in modo che non venga alterato nell'intero script anche se usato in uno stile non quotato ( o.foo ). Esempio:

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
1
var 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 o.foo completamente. Ad esempio la proprietà o.foo si o.foo in o._$foo$_ con questa opzione. Ciò consente la manipolazione della proprietà di una grande base di codice pur essendo ancora 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
1
var 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 o.foo in o._$foo$XYZ_ . Puoi 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 la modifica della manipolazione 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 nella memoria.

Riferimento API

Supponendo l'installazione tramite NPM, puoi caricare UglifyJS nella tua applicazione in questo modo:

1
var UglifyJS = require("uglify-js");

Esiste un'unica funzione di alto livello, minify(code, options) , che eseguirà tutte le fasi di minification in modo configurabile. Per impostazione predefinita minify() abiliterà le opzioni compress e mangle . Esempio:

1 2 3 4
var 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 i nomi dei file ei valori sono il codice sorgente:

1 2 3 4 5 6 7
var 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));

Il toplevel di opzioni:

1 2 3 4 5 6 7 8
var 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'opzione nameCache :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var 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));

È possibile 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 16
var 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 opzioni minify() :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
var 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 6
var 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 3
var 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 , the API 3.x` non genera errori. Per ottenere un effetto simile si potrebbe fare quanto segue:

1 2
var result = UglifyJS.minify(code, options); if (result.error) throw result.error;

Riduci le opzioni

  • warnings (default false ) - passa true per restituire gli avvisi del compressore in result.warnings . Usa il valore "verbose" per avvisi più dettagliati.

  • parse (default {} ) - passa un oggetto se desideri specificare alcune opzioni di analisi aggiuntive.

  • compress (default {} ) - passa false per saltare completamente la compressione. Passa un oggetto per specificare le opzioni di compressione personalizzate.

  • mangle (default true ) - passa false per saltare i nomi di manipolazione, o passa un oggetto per specificare le opzioni di mangle (vedi sotto).

    • mangle.properties (default false ) - una sottocategoria dell'opzione mangle Passa un oggetto per specificare le opzioni di proprietà mangle personalizzate.
  • output (default null ) - passa un oggetto se desideri specificare ulteriori opzioni di output I valori predefiniti sono ottimizzati per la migliore compressione.

  • sourceMap (default false ) -passa un oggetto se desideri specificare le opzioni della mappa di origine .

  • toplevel (default false ) toplevel a true se si desidera abilitare la modifica del nome della funzione e della variabile di primo livello e per eliminare le variabili e le funzioni inutilizzate.

  • nameCache (default null ) nameCache un oggetto vuoto {} o un oggetto nameCache utilizzato in precedenza se desideri memorizzare nella cache nomi di proprietà e variabili nameCache su più invocazioni di minify() . Nota: questa è una proprietà di lettura / scrittura. minify() farà leggere lo stato della cache dei nomi di questo oggetto e aggiornarlo durante la minificazione in modo che possa essere riutilizzato o mantenuto esternamente dall'utente.

  • ie8 (valore predefinito false ): impostato su true per supportare IE8.

  • keep_fnames (default: false ) -pass true per evitare di scartare o alterare i nomi delle funzioni Utile per il codice che si basa su Function.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 8
var 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, è solo 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'attributo del file (vedere le specifiche ) nel file della mappa di origine.

È possibile impostare l'opzione sourceMap.url come "inline" e la mappa di origine verrà aggiunta al codice.

È inoltre possibile specificare la proprietà sourceRoot da includere nella mappa di origine:

1 2 3 4 5 6
var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, { sourceMap: { root: "http://example.com/src", url: "out.js.map" } });

Se stai comprimendo JavaScript compilato e hai una mappa sorgente per esso, puoi usare sourceMap.content :

1 2 3 4 5 6 7
var 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'intestazione X-SourceMap , puoi semplicemente omettere sourceMap.url .

Opzioni di analisi

  • bare_returns (default false ) - supporta le dichiarazioni di return primo livello

  • html5_comments (valore predefinito true )

  • shebang (valore predefinito true ) - supporta il #!command come prima riga

Opzioni di compressione

  • arguments (default: true ) - sostituisci arguments[index] con il nome del parametro della funzione quando possibile.

  • booleans (predefinito: true ) - varie ottimizzazioni per il contesto booleano, ad esempio !!a ? b : c → a ? b : c

  • collapse_vars (default: true ) - Comprimi variabili non costanti monouso, effetti collaterali permettendo.

  • comparisons (default: true ) - applica alcune ottimizzazioni ai nodi binari, ad esempio !(a <= b) → a > b , tenta di negare i nodi binari, ad esempio a = !b && !c && !d && !e → a=!(b||c||d||e) ecc.

  • conditionals (default: true ) - applica le ottimizzazioni per if -s e le espressioni condizionali

  • dead_code (default: true ) - rimuove il codice non raggiungibile

  • drop_console (default: false ) - Passa true per scartare le chiamate alle funzioni console.* Se desideri eliminare una chiamata di funzione specifica come console.info e / o conservare gli effetti collaterali dagli argomenti della funzione dopo aver abbandonato la chiamata alla funzione, usa pure_funcs anziché.

  • drop_debugger (predefinito: true ) - rimuove le istruzioni del debugger;

  • evaluate (predefinito: true ) - tenta di valutare espressioni costanti

  • expression (predefinito: false ) - Passa true per preservare i valori di completamento dalle istruzioni del terminale senza return , ad esempio nei bookmarklet.

  • global_defs (default: {} ) - vedi compilazione condizionale

  • hoist_funs (default: false ) - dichiarazioni della funzione hoist

  • hoist_props (default: 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(op, oq); is convertito in f(1, 2); Nota: hoist_props funziona meglio con mangle abilitato, l'opzione compress passes impostata su 2 o superiore e l'opzione compress toplevel abilitata.

  • hoist_vars (default: false ) - dichiarazioni di hoist var (questo è false per impostazione predefinita perché sembra aumentare la dimensione dell'output in generale)

  • if_return (default: true ) - ottimizzazioni per if / return e if / continue

  • inline (default: true ) - chiamate inline alla funzione con istruzione semplice / return :

    • false - uguale a 0
    • 0 - inlining disabilitato
    • 1 - funzioni semplici in linea
    • 2 - funzioni inline con argomenti
    • 3 - funzioni inline con argomenti e variabili
    • true - uguale a 3
  • join_vars (default: true ) - unisce istruzioni var consecutive

  • keep_fargs (default: true ) - Impedisce al compressore di scartare gli argomenti della funzione inutilizzati, necessario per il codice che si basa su Function.length .

  • keep_fnames (default: false ) - Passa true per impedire al compressore di scartare i nomi delle funzioni Utile per il codice che si basa su Function.prototype.name Vedi anche: l' opzione keep_fnames mangle .

  • keep_infinity (impostazione predefinita: false ) - Passa true per evitare che Infinity venga compresso in 1/0 , il che potrebbe causare problemi di prestazioni su Chrome.

  • loops (default: true ) - ottimizzazioni for cicli do , while e for quando possiamo determinare staticamente la condizione.

  • negate_iife (default: true ) - nega "Espressioni di funzione immediatamente richiamate" dove il valore restituito viene scartato, per evitare le parentesi che il generatore di codice inserirà.

  • passes (predefinito: 1 ) - Il numero massimo di volte per eseguire compress. In alcuni casi più di un passaggio porta a ulteriore compressione del codice. Tieni presente che più passaggi richiederanno più tempo.

  • properties (default: true ) - riscrive l'accesso alle proprietà usando la notazione punto, ad esempio foo["bar"] → foo.bar

  • pure_funcs (default: null ) - Puoi passare un array di nomi e UglifyJS presumerà che quelle 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 variabile q non viene utilizzata altrove, UglifyJS la lascerà cadere, ma manterrà comunque la Math.floor(a/b) , senza sapere cosa fa. Puoi passare pure_funcs: [ 'Math.floor' ] per fargli sapere che questa funzione non produrrà alcun effetto collaterale, nel qual caso l'intera istruzione verrebbe scartata. L'implementazione corrente aggiunge un po' di overhead (la compressione sarà più lenta). Assicurati che anche i simboli sotto pure_funcs siano sotto mangle.reserved per evitare mutilazioni.

  • pure_getters (default: "strict" ) - Se passi true per questo, UglifyJS presumerà che l'accesso alla proprietà dell'oggetto (ad esempio foo.bar o foo["bar"] ) non abbia effetti collaterali. Specifica "strict" a considera foo.bar come foo.bar di effetti collaterali solo quando foo è certo di non lanciare, cioè non è null o undefined .

  • reduce_funcs (predefinito: true ): consente di inserire inline le funzioni monouso come espressioni di funzione quando consentito, consentendo un'ulteriore ottimizzazione. Abilitato per impostazione predefinita. L'opzione dipende reduce_vars . Alcuni codici vengono eseguiti più velocemente nel motore Chrome V8 se questa opzione è disabilitata Non influisce negativamente sugli altri principali browser.

  • reduce_vars (default: true ) - Migliora l'ottimizzazione delle variabili assegnate e usate come valori costanti.

  • sequences (default: true ) - unisce istruzioni semplici consecutive utilizzando l'operatore virgola. Può essere impostato su un numero intero positivo per specificare il numero massimo di sequenze virgole consecutive che verranno generate. Se questa opzione è impostata su true il limite di sequences predefinito è 200 Imposta l'opzione su false o 0 per disabilitare. La lunghezza minima delle sequences è 2 Un valore di sequences di 1 è considerato equivalente a true e come tale significa 200 In rare occasioni il limite di sequenze predefinito porta a tempi di compressione molto lenti in tal caso si consiglia un valore di 20 o inferiore.

  • side_effects (default: true ) - Passa false per disabilitare le funzioni potenzialmente side_effects contrassegnate come "pure". Una chiamata di funzione è contrassegnata come "pura" se un'annotazione di commento /*@__PURE__*/ o /*#__PURE__*/ precede immediatamente call. Ad esempio: /*@__PURE__*/foo();

  • switches (default: true ) - deduplica e rimuove i rami switch non raggiungibili

  • toplevel (default: false ) - elimina funzioni non referenziate ( "funcs" ) e / o variabili ( "vars" ) nell'ambito di primo livello ( false per impostazione predefinita, true per eliminare sia le funzioni che le variabili non referenziate)

  • top_retain (default: null ) - impedisce la rimozione unused specifiche funzioni e variabili di primo livello (può essere array, separato da virgole, RegExp o funzione. Implica toplevel )

  • typeofs (default: true ) - Trasforma typeof foo == "undefined" in foo === void 0 Nota: si consiglia di impostare questo valore su false per IE10 e versioni precedenti a causa di problemi noti.

  • unsafe (default: false ) - applica trasformazioni "unsafe" (discussione sotto)

  • unsafe_comps (default: false ) - comprime espressioni come a <= b assumendo che nessuno degli operandi possa essere (costretto a) NaN .

  • unsafe_Function (default: false ) - Function(args, code) compressione e manipolazione Function(args, code) quando sia args che code sono stringhe letterali.

  • unsafe_math (default: false ) - ottimizza espressioni numeriche come 2 * x * 3 in 6 * x , che possono fornire risultati in virgola mobile imprecisi.

  • unsafe_proto (default: false ) - ottimizza espressioni come Array.prototype.slice.call(a) in [].slice.call(a)

  • unsafe_regexp (default: false ) - abilita le sostituzioni di variabili con valori RegExp come se fossero costanti.

  • unsafe_undefined (default: false ) - sostituisci void 0 se c'è una variabile chiamata undefined nell'ambito (il nome della variabile sarà alterato, tipicamente ridotto a un singolo carattere)

  • unused (default: true ) - elimina funzioni e variabili non referenziate (le assegnazioni di variabili dirette semplici non contano come riferimenti a meno che non siano impostate su "keep_assign" )

  • warnings (default: false ) - visualizza gli avvisi quando si rilascia codice non raggiungibile o dichiarazioni inutilizzate ecc.

Opzioni Mangle

  • eval (valore predefinito false ) - Passa true a falsificare i nomi visibili negli ambiti in cui vengono utilizzati eval o with .

  • keep_fnames (default false ) - Passa true per non manipolare i nomi delle funzioni Utile per il codice che si basa su Function.prototype.name Vedi anche: l' opzione di compressione keep_fnames .

  • reserved (predefinito [] ) - Passa un array di identificatori che dovrebbero essere esclusi dalla manipolazione. Esempio: ["foo", "bar"] .

  • toplevel (default false ) - Passa true ai nomi mangle dichiarati nell'ambito di primo livello.

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 10
var 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 (default: false ) - Usa true per consentire la manipolazione delle proprietà DOM incorporate. Non è consigliabile sovrascrivere questa impostazione.

  • debug (default: false ) -— Mangia 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 (default: false ) -— Solo manipola i nomi di proprietà non keep_quoted .

  • regex (default: null ) - Passa un valore letterale RegExp per manipolare solo i nomi delle proprietà che corrispondono all'espressione regolare.

  • reserved (predefinito: [] ) - Non alterare i nomi delle proprietà elencati nell'array reserved .

Opzioni di output

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 ). Facoltativamente puoi passare argomenti aggiuntivi che controllano l'output del codice:

  • ascii_only (valore predefinito false ): ascii_only escape dei caratteri Unicode nelle stringhe e nelle espressioni regolari (influisce sulle direttive con caratteri non ascii che diventano non valide)

  • beautify (default true ) - se abbellire effettivamente l'output. Il passaggio di -b lo imposterà a true, ma potrebbe essere necessario passare -b anche quando si desidera generare codice minimizzato, al fine di specificare argomenti aggiuntivi, quindi è possibile usa -b beautify=false per sovrascriverlo.

  • braces (valore predefinito false ): inserisce sempre le parentesi graffe nelle istruzioni if , for , do , while o with , anche se il loro corpo è una singola istruzione.

  • comments (valore predefinito false ) - passa true o "all" per conservare tutti i commenti, "some" per preservare alcuni commenti, una stringa di espressione regolare (ad esempio /^!/ ) o una funzione.

  • indent_level (predefinito 4 )

  • indent_start (default 0 ) - indent_start tutte le righe altrettanti spazi

  • inline_script (valore predefinito true ): inline_script i commenti HTML e la barra nelle occorrenze di </script> nelle stringhe

  • keep_quoted_props (default false ) - quando attivato, impedisce di eliminare le virgolette dai nomi di proprietà nei valori letterali degli oggetti.

  • max_line_len (default false ) - lunghezza massima della riga (per codice uglified)

  • preamble (predefinito null ) - quando viene 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 (default false ) - passa true per preservare le linee, ma funziona solo se beautify è impostato su false .

  • quote_keys (default false ) - passa true per citare tutte le chiavi negli oggetti letterali

  • quote_style (default 0 ) - stile di virgolette preferito per le stringhe (influisce anche sui nomi delle proprietà e sulle direttive citate):

    • 0 - preferisce le virgolette doppie, passa alle virgolette singole quando ci sono più virgolette doppie nella stringa stessa. 0 è il migliore per la dimensione gzip.
    • 1 - usa sempre virgolette singole
    • 2 - usa sempre le virgolette doppie
    • 3 - usa sempre le virgolette originali
  • semicolons (valore predefinito true ) - istruzioni separate con punto e virgola. Se passi false quando possibile useremo una nuova riga invece di un punto e virgola, portando a un output più leggibile di codice semplificato (la dimensione prima di gzip potrebbe essere più piccola; la dimensione dopo gzip non significativamente più grande ).

  • shebang (default true ) - conserva shebang #! nel preambolo (script bash)

  • webkit (default false ) - abilita soluzioni alternative per i bug di WebKit. Gli utenti di PhantomJS dovrebbero impostare questa opzione su true .

  • width (impostazione predefinita 80 ) - 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 (default false ) - passa true per racchiudere le espressioni di funzione invocate immediatamente. Vedi # 640 per maggiori dettagli.

Miscellanea

--comments passare da te - --comments . Conserva determinati commenti L'output Per impostazione predefinita in stile IT manterrà JSDoc che contengono commenti "@preserve", "@license" o "@cc_on" (compilazione condizionale per IE) Passare da te CAN. --comments all per mantenere tutti i commenti, o --comments all JavaScript valida per mantenere solo i commenti che corrispondono a questa --comments /^!/ . 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 7
function 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 è associato il commento) viene scartata dal compressore in quanto non referenziata.

I commenti più sicuri in cui inserire le informazioni sul copyright (o altre informazioni che devono essere conservate nell'output) sono commenti allegati ai nodi di livello superiore.

L'opzione di compress unsafe

Abilita alcune trasformazioni che potrebbero interrompere la logica del codice in alcuni casi artificiosi, 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) o Array(1, 2, 3)[ 1, 2, 3 ]
  • new Object(){}
  • String(exp) o exp.toString()"" + exp
  • new Object/RegExp/Function/Error/Array (...) → scartiamo il new

Conditional compilation

È possibile utilizzare l' --define ( -d ) per dichiarare le variabili globali che UglifyJS assumerà come costanti (a meno che non siano definite nell'ambito). Ad esempio, se si passa --define DEBUG=false , insieme alla rimozione del codice --define DEBUG=false UglifyJS eliminerà quanto segue dall'output:

1 2 3
if (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 il codice non è raggiungibile; per ora non è possibile disattivare solo questo avviso specifico, è possibile passare warnings=false per disattivare tutti gli avvisi.

Un altro modo per farlo è dichiarare le tue variabili globali come costanti in un file separato e includerle nella build. Ad esempio puoi avere un file build/defines.js con quanto segue:

1 2 3
var DEBUG = false; var PRODUCTION = true; // etc.

e crea il tuo codice in questo modo:

1
uglifyjs 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à codice non raggiungibile come al solito. La build conterrà le dichiarazioni const se le usi. Se stai prendendo di mira ambienti <ES6 che non supporta const , dovrebbe essere sufficiente usare var con reduce_vars (abilitato per impostazione predefinita).

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 8
var 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 chiave global_defs "@" per istruire UglifyJS ad analizzare il valore come un'espressione:

1 2 3 4 5 6 7 8
UglifyJS.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 8
UglifyJS.minify("alert('hello');", { compress: { global_defs: { "alert": "console.log" } } }).code; // returns: '"console.log"("hello");'

Utilizzo di Uglify AST nativo con minify 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 di albero di sintassi astratto; per ragioni pratiche non possiamo facilmente passare all'uso interno di SpiderMonkey AST Tuttavia, UglifyJS ora ha un convertitore che può importare un SpiderMonkey AST.

Ad esempio Acorn è un parser super veloce che produce SpiderMonkey AST. 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:

1
acorn file.js | uglifyjs -p spidermonkey -m -c

L'opzione -p spidermonkey 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 trasformiamo semplicemente quell'AST nel nostro AST interno.

Use Acorn for parsing

Più per divertimento, ho aggiunto l'opzione -p acorn che userà Acorn per fare tutto il parsing.Se passi questa opzione, UglifyJS require("acorn") .

Acorn è molto veloce (es. 250 ms invece di 380 ms su un codice 650K), ma la conversione dell'albero SpiderMonkey che Acorn produce 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% della riduzione delle dimensioni del codice minificato per la maggior parte delle trasformazioni di codice non elaborate in JavaScript. Si può semplicemente disabilitare la compress per accelerare le build di Uglify da 3 a 4 volte. In questo veloce modalità solo mangle Uglify ha velocità di minimizzazione e dimensioni gzip comparabili a butternut :

d3.js minimizza le dimensioni dimensione gzip minimizza il tempo (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:

1
uglifyjs file.js -m

Per abilitare la modalità di minimizzazione rapida con l'API utilizzare:

1
UglifyJS.minify(code, { compress: false, mangle: true });

Mappe di origine e debug

È noto che varie trasformazioni di compress che semplificano, riorganizzano, incorporano e rimuovono il codice hanno un effetto negativo sul debug con le mappe sorgente. Ciò è previsto poiché il codice è ottimizzato e le mappature spesso non sono possibili poiché parte del codice non esiste più. Per la massima fedeltà in il debug della mappa sorgente disabilita l'opzione Uglify compress e usa semplicemente mangle .

Compiler assumptions

Per consentire migliori ottimizzazioni, il compilatore fa vari presupposti:

  • .toString() e .valueOf() non hanno effetti collaterali e per gli oggetti incorporati non sono stati sovrascritti.
  • undefined , NaN e Infinity non sono stati ridefiniti esternamente.
  • arguments.callee , arguments.caller e Function.prototype.caller non vengono utilizzati.
  • Il codice non si aspetta che il contenuto di Function.prototype.toString() o Error.prototype.stack sia qualcosa in particolare.
  • Ottenere e impostare le proprietà su un oggetto semplice non causa altri effetti collaterali (usando .watch() o Proxy ).
  • Object properties can be added , rimosse e modificate (non impedito con Object.defineProperty() , Object.defineProperties() , Object.freeze() , Object.preventExtensions() o Object.seal() ).