Fantastico modulo comunitario

UglifyJS 3

UglifyJS è un toolkit per parser, minimizzazione, compressione e abbellimento JavaScript.

Nota:

  • uglify-js@3ha un'API e una CLI semplificate che non sono retrocompatibili conuglify-js@2 .
  • La documentazione per 2.xle versioni UglifyJS può essere trovata qui .
  • uglify-jssupporta 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:

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à 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:

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 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 che X-SourceMapvenga utilizzato HTTP e ometterà 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 manipolerà file1.jse file2.js, trascinerà l'output in foo.min.jse la mappa sorgente in foo.min.js.map. La mappatura sorgente farà riferimento a http://foo.com/src/js/file1.jse 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.jse 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:

1
uglifyjs 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(default false) -- modifica i nomi dichiarati nell'ambito del livello superiore.

  • eval(impostazione predefinita false) -- modifica i nomi visibili negli ambiti in cui vengono utilizzati evalo .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:

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

per evitare che i nomi require, exportse $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-propsper 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
1
var 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 reservedproprietà:

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._());

Modifica tutte le proprietà corrispondenti 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 delle opzioni delle proprietà di 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 qualche utilità, evitiamo di modificare i nomi JS standard per impostazione predefinita ( --mangle-props builtinsper sovrascrivere).

Viene fornito un file di esclusione predefinito tools/domprops.jsonche dovrebbe coprire la maggior parte delle proprietà JS e DOM standard definite in vari browser. Passa --mangle-props dompropsper 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.jse part2.jssaranno 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
1
var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);

Debugging property name mangling

Puoi anche passare --mangle-props debugper 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
1
var 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.fooin 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:

1
var 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 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 minifypiù 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 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));

L' toplevelopzione:

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' nameCacheopzione:

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));

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 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 combinazione di minify()opzioni:

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, l' 3.xAPI 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;

Minimizza le opzioni

  • warnings(impostazione predefinita false) - passa trueper restituire gli avvisi del compressore in result.warningsUtilizzare il valore "verbose"per avvisi più dettagliati.

  • parse(impostazione predefinita {}) — passa un oggetto se desideri specificare alcune opzioni di analisi aggiuntive .

  • compress(impostazione predefinita {}): passa falseper ignorare completamente la compressione. Passa un oggetto per specificare le opzioni di compressione personalizzate .

  • mangle(default true) — passa falseper saltare la modifica dei nomi o passa un oggetto per specificare le opzioni di modifica (vedi sotto).

  • output(impostazione predefinita null): passa un oggetto se desideri specificare opzioni di output aggiuntive . Le impostazioni predefinite sono ottimizzate per la migliore compressione.

  • sourceMap(impostazione predefinita false) - passa un oggetto se desideri specificare le opzioni della mappa sorgente .

  • toplevel(impostazione predefinita false) - impostare su truese 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 predefinita null) - passa un oggetto vuoto {}o un oggetto utilizzato in precedenza nameCachese desideri memorizzare nella cache nomi di variabili e proprietà alterate attraverso più invocazioni di minify(). 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 predefinita false) - impostato per truesupportare IE8.

  • keep_fnames(default: false) - passaggio trueper 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

Tieni presente che la mappa di origine non viene salvata in un file, viene semplicemente restituita in result.map. Il valore passato per sourceMap.urlviene utilizzato solo per impostare //# sourceMappingURL=out.js.mapin result.code. Il valore di filenameviene utilizzato solo per impostare filel'attributo (vedere le specifiche ) nel file di mappa di origine.

È possibile impostare l'opzione sourceMap.urlsu 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 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 disponi di una mappa sorgente, puoi utilizzare 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' X-SourceMapintestazione, puoi semplicemente omettere sourceMap.url.

Opzioni di analisi

  • bare_returns(impostazione predefinita false) - supporta returnle dichiarazioni di livello superiore

  • html5_comments(predefinito true)

  • shebang(impostazione predefinita true) - supporto #!commandcome prima riga

Opzioni di compressione

  • arguments(impostazione predefinita: true) -- sostituire arguments[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 esempio a = !b && !c && !d && !e → a=!(b||c||d||e)ecc.

  • conditionals(impostazione predefinita: true) -- applica ottimizzazioni per if-s ed espressioni condizionali

  • dead_code(impostazione predefinita: true) -- rimuove il codice irraggiungibile

  • drop_console(impostazione predefinita: false) -- Passa trueper scartare le chiamate alle console.*funzioni.Se desideri eliminare una chiamata di funzione specifica come console.infoe/o conservare gli effetti collaterali degli argomenti della funzione dopo aver eliminato la chiamata di funzione, utilizza pure_funcsinvece.

  • drop_debugger(impostazione predefinita: true) -- rimuove debugger;le istruzioni

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

  • expression(impostazione predefinita: false) -- Passa trueper preservare i valori di completamento dalle istruzioni terminali senza return, ad esempio nei bookmarklet.

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

  • hoist_funs(default: false) -- dichiarazioni della funzione di sollevamento

  • hoist_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 in f(1, 2);. Nota: hoist_props funziona meglio con mangleabilitato, l' compressopzione passesimpostata su 2o superiore e l' compressopzione toplevelabilitata.

  • hoist_vars(default: false) -- vardichiarazioni 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/continue

  • inline(impostazione predefinita: true) -- chiamate in linea alla funzione con returnl'istruzione semplice/:

    • false--uguale a0
    • 0-- Incorporamento disabilitato
    • 1-- Funzioni semplici in linea
    • 2-- funzioni inline con argomenti
    • 3-- funzioni inline con argomenti e variabili
    • true--uguale a3
  • join_vars(impostazione predefinita: true) -- unisce varistruzioni consecutive

  • keep_fargs(impostazione predefinita: 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 trueper impedire al compressore di scartare i nomi delle funzioni. Utile per il codice che si basa su Function.prototype.name. Vedi anche: l' keep_fnames opzione mangle .

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

  • loops(impostazione predefinita: true) -- ottimizzazioni per do, whilee forcicli 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 variabile qè non utilizzato altrove, UglifyJS lo eliminerà, ma manterrà comunque il Math.floor(a/b), non sapendo 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'attuale implementazione aggiunge un po' di sovraccarico (la compressione sarà più lenta). Assicurati che i simboli sotto pure_funcs siano anche sotto mangle.reservedper evitare alterazioni.

  • pure_getters(impostazione predefinita: "strict") -- Se passi trueper questo, UglifyJS presuppone che l'accesso alle proprietà dell'oggetto (ad esempio foo.baro foo["bar"]) non abbia effetti collaterali. Specifica "strict"di trattare foo.barcome privo di effetti collaterali solo quando fooè sicuro di non lanciare, cioè non nullO undefined.

  • 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 dipende reduce_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, trueil sequenceslimite predefinito è 200. Imposta opzione a falseo 0 per disabilitare. La sequenceslunghezza più piccola è 2. Un sequencesvalore di 1 è considerato equivalente a truee come tale significa 200. In rare occasioni il limite di sequenze predefinito porta a tempi di compressione molto lenti, nel qual caso 20si consiglia un valore pari o inferiore.

  • side_effects(impostazione predefinita: true) -- Passa falseper 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 rimuove switchi rami non raggiungibili

  • toplevel(impostazione predefinita: false) -- rilascia funzioni senza riferimenti ( "funcs") e/o variabili ( "vars") nell'ambito di livello superiore ( falseper impostazione predefinita, trueper eliminare sia le funzioni che le variabili senza riferimenti)

  • top_retain(impostazione predefinita: null) -- impedisce unusedla rimozione di funzioni e variabili di livello superiore specifiche (può essere un array, separato da virgole, RegExp o una funzione. Implica toplevel)

  • typeofs(impostazione predefinita: true) - Si trasforma typeof foo == "undefined"in foo === void 0.Nota: si consiglia di impostare questo valore su falseper 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 se a <= bsi presupponesse che nessuno degli operandi possa essere (costringuto a) NaN.

  • unsafe_Function(impostazione predefinita: false) -- comprime e altera Function(args, code) quando entrambi argse codesono stringhe letterali.

  • unsafe_math(impostazione predefinita: false) -- ottimizza le espressioni numeriche come 2 * x * 3into 6 * x, che potrebbero fornire risultati in virgola mobile imprecisi.

  • unsafe_proto(impostazione predefinita: false) -- ottimizza le espressioni come Array.prototype.slice.call(a)into[].slice.call(a)

  • unsafe_regexp(impostazione predefinita: false) - abilita la sostituzione delle variabili con RegExpvalori come se fossero costanti.

  • unsafe_undefined(impostazione predefinita: false) -- sostituisce void 0se è presente una variabile denominata undefinednell'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 predefinita false) -- Passa trueper modificare i nomi visibili negli ambiti in cui vengono utilizzati evalo .with

  • keep_fnames(default false) -- Passa trueper non modificare i nomi delle funzioni. Utile per il codice che si basa su Function.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(default false) -- Passa truea 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 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(impostazione predefinita: false) -- Da utilizzare trueper 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'array reserved.

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(default false) -- escape caratteri Unicode in stringhe ed espressioni regolari (influenza le direttive con caratteri non-ascii che diventano non validi)

  • beautify(impostazione predefinita true) - se abbellire effettivamente l'output. Il passaggio -blo imposterà su true, ma potrebbe essere necessario passare -banche quando si desidera generare codice minimizzato, per specificare argomenti aggiuntivi, in modo da poterlo utilizzare -b beautify=falseper sovrascriverlo.

  • braces(impostazione predefinita false) -- inserisce sempre le parentesi graffe nelle istruzioni if, for, o , anche se doil loro corpo è una singola istruzione.whilewith

  • comments(default false) -- passa trueo "all"per preservare 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) -- prefisso tutte le righe con quel numero di spazi

  • inline_script(impostazione predefinita true) -- evita i commenti HTML e la barra nelle occorrenze di </script>stringhe

  • keep_quoted_props(impostazione predefinita false) -- se attivato, impedisce di rimuovere le virgolette dai nomi delle proprietà nei valori letterali degli oggetti.

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

  • preamble(default null) -- 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 predefinita false) - passa trueper preservare le righe, ma funziona solo se beautifyè impostato su false.

  • quote_keys(default false) -- passa trueper virgolette tutte le chiavi negli oggetti letterali

  • quote_style(default 0) -- 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 singole
    • 2-- usa sempre le virgolette doppie
    • 3-- usa sempre le virgolette originali
  • semicolons(default true) -- separa le istruzioni con punto e virgola. Se lo passi, falsequando 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 predefinita true) -- preserva shebang #!nel preambolo (script bash)

  • webkit(impostazione predefinita false) - abilita soluzioni alternative per i bug di WebKit. Gli utenti 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 trueper racchiudere le espressioni di funzioni immediatamente invocate. Vedi #640 per maggiori dettagli.

Varie

Puoi passare --commentsper 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 allper 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 7
function 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 compressopzione

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)oppure Array(1, 2, 3)[ 1, 2, 3 ]
  • new Object(){}
  • String(exp)oppure exp.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 3
if (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=falsea 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.jsfile con quanto segue:

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

e costruisci 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 in base al valore stesso e rilascerà il codice irraggiungibile come al solito. La build conterrà le constdichiarazioni se le usi. Se stai prendendo di mira ambienti <ES6 che non not support const, l'utilizzo varcon 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_defsed è 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 global_defschiave il prefisso "@"per indicare a UglifyJS di 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");'

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 TreeWalkere 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:

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

L' -p spidermonkeyopzione 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 acornopzione 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 compressper 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:

1
uglifyjs file.js -m

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

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

Mappe di origine e debug

È noto che varie compresstrasformazioni 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' compressopzione 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.
  • undefinede NaNnon Infinitysono stati ridefiniti esternamente.
  • arguments.calleee arguments.callernon Function.prototype.callervengono utilizzati.
  • Il codice non prevede che il contenuto Function.prototype.toString()o Error.prototype.stacksia qualcosa in particolare.
  • Ottenere e impostare proprietà su un oggetto semplice non causa altri effetti collaterali (usando .watch()o Proxy).
  • Le proprietà dell'oggetto possono essere aggiunte , rimosse e modificate (non impedite con Object.defineProperty(), Object.defineProperties(), o ).Object.freeze()Object.preventExtensions()Object.seal()