Mòdul comunitari fantàstic

UglifyJS 3

UglifyJS és un conjunt d'eines d'analitzador, minificador, compressor i embellidor de JavaScript.

Nota:

  • uglify-js@3té una API i una CLI simplificades que no són compatibles ambuglify-js@2 .
  • La documentació per a 2.xles versions d'UglifyJS es pot trobar aquí .
  • uglify-jsnomés admet JavaScript (ECMAScript 5).
  • Per minimitzar ECMAScript 2015 o superior, transpileu amb eines com Babel .

Instal·lar

Primer assegureu-vos que heu instal·lat la darrera versió de node.js (pot ser que hàgiu de reiniciar l'ordinador després d'aquest pas).

Des de NPM per utilitzar-lo com a aplicació de línia d'ordres:

1
npm install uglify-js -g

De NPM per a ús programàtic:

1
npm install uglify-js

Ús de la línia d'ordres

1
uglifyjs [input files] [options]

UglifyJS pot prendre diversos fitxers d'entrada. És recomanable que primer passeu els fitxers d'entrada i després passeu les opcions. UglifyJS analitzarà els fitxers d'entrada en seqüència i aplicarà qualsevol opció de compressió. Els fitxers s'analitzen en el mateix àmbit global, és a dir, una referència d'un fitxer a alguna variable/funció declarada en un altre fitxer es farà coincidir correctament.

Si no s'especifica cap fitxer d'entrada, UglifyJS llegirà des de STDIN.

Si voleu passar les vostres opcions abans dels fitxers d'entrada, separeu-los amb un guió doble per evitar que els fitxers d'entrada s'utilitzin com a arguments d'opció:

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.

Especifiqueu --output( -o) per declarar el fitxer de sortida. En cas contrari, la sortida passa a STDOUT.

Opcions de mapa font de la CLI

UglifyJS pot generar un fitxer de mapa font, que és molt útil per depurar el vostre JavaScript comprimit. Per obtenir un mapa font, passeu --source-map --output output.js(el mapa font s'escriurà a output.js.map).

Opcions addicionals:

  • --source-map "filename='<NAME>'"per especificar el nom del mapa font.

  • --source-map "root='<URL>'"per passar l'URL on es poden trobar els fitxers originals.

  • --source-map "url='<URL>'"per especificar l'URL on es pot trobar el mapa d'origen. En cas contrari, UglifyJS assumeix que X-SourceMaps'està utilitzant HTTP i ometrà la //# sourceMappingURL=directiva.

Per exemple:

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'"

L'anterior comprimirà i manipularà file1.jsi file2.js, deixarà anar la sortida foo.min.jsi el mapa d'origen a foo.min.js.map. El mapeig d'origen es referirà a http://foo.com/src/js/file1.jsi http://foo.com/src/js/file2.js(de fet apareixerà http://foo.com/src com a arrel del mapa d'origen, i els fitxers originals com js/file1.jsa i js/file2.js).

Composed source map

Quan esteu comprimint codi JS generat per un compilador com ara CoffeeScript, la correspondència amb el codi JS no serà massa útil. En comptes d'això, us agradaria tornar al codi original (és a dir, CoffeeScript). UglifyJS té un opció per prendre un mapa d'origen d'entrada. Suposant que teniu un mapeig de CoffeeScript → JS compilat, UglifyJS pot generar un mapa de CoffeeScript → JS comprimit assignant cada testimoni del JS compilat a la seva ubicació original.

Per utilitzar aquesta característica passa --source-map "content='/path/to/input/source.map'" o --source-map "content=inline"si el mapa font s'inclou en línia amb les fonts.

Opcions de compressió CLI

Heu de passar --compress( -c) per habilitar el compressor. Opcionalment podeu passar una llista d' opcions de compressió separades per comes .

Les opcions estan en la forma foo=bar, o només foo(aquest últim implica una opció booleana que voleu establir true; efectivament és una drecera per a foo=true).

Exemple:

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

Opcions de mangle CLI

Per habilitar el mangler, heu de passar --mangle( -m). S'admeten les opcions següents (separades per comes):

  • toplevel(per defecte false) -- modifica els noms declarats a l'àmbit de nivell superior.

  • eval(per defecte false) -- modifica els noms visibles als àmbits on s'utilitzen evalo .with

Quan la manipulació està activada però voleu evitar que determinats noms siguin alterats, podeu declarar aquests noms amb --mangle reserved— passeu una llista de noms separats per comes. Per exemple:

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

per evitar que els noms require, exportsi $es canviïn.

CLI modifica els noms de propietats ( --mangle-props)

Nota: AIXÒ PROBABLEMENT TRENCARÀ EL TEU CODI. La manipulació dels noms de propietat és un pas independent, diferent de la manipulació de noms de variables. Passa --mangle-propsper activar-la. Manipularà totes les propietats del codi d'entrada, a excepció de les propietats DOM integrades i les propietats del JavaScript bàsic. classes. Per exemple:

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

Manipular totes les propietats (excepte 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());

Destrossa totes les propietats excepte reservedles propietats:

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

Destrossa totes les propietats que coincideixen amb 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());

Opcions de combinació de propietats de 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());

Perquè això sigui útil, evitem alterar els noms JS estàndard per defecte ( --mangle-props builtinsper substituir).

Es proporciona un fitxer d'exclusió predeterminat tools/domprops.jsonque hauria de cobrir la majoria de propietats estàndard de JS i DOM definides en diversos navegadors. Passeu --mangle-props dompropsper desactivar aquesta funció.

Es pot utilitzar una expressió regular per definir quins noms de propietat s'han de modificar. Per exemple, --mangle-props regex=/^_/només es manipularan els noms de propietat que comencen amb un guió baix.

Quan comprimiu diversos fitxers amb aquesta opció, per tal que al final funcionin junts, hem d'assegurar-nos d'alguna manera que una propietat es destrueixi amb el mateix nom en tots. Per això, passeu --name-cache filename.json i UglifyJS mantindrà aquests mapes en un fitxer que després es pot reutilitzar. Inicialment hauria d'estar buit. Exemple:

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

Ara, part1.jsi part2.jsseran coherents entre si pel que fa als noms de propietats alterats.

L'ús de la memòria cau de noms no és necessari si comprimiu tots els fitxers en una sola trucada a UglifyJS.

Manipulació de noms sense cometes ( --mangle-props keep_quoted)

Si utilitzeu el nom de propietat entre cometes ( o["foo"]) es reserva el nom de la propietat ( foo) de manera que no es deformi en tot l'script, fins i tot quan s'utilitza amb un estil sense cometes ( o.foo). Exemple:

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

També podeu passar --mangle-props debugper alterar els noms de les propietats sense enfosquir-los completament. Per exemple, la propietat o.foo es modificaria o._$foo$_amb aquesta opció. Això permet manipular propietats d'una base de codi gran, alhora que podeu depurar el codi i identificar on la manipulació està trencant les coses.

1
$ uglifyjs stuff.js --mangle-props debug -c -m
1
var o={_$foo$_:1,_$bar$_:3};o._$foo$_+=o._$bar$_,console.log(o._$foo$_);

També podeu passar un sufix personalitzat amb --mangle-props debug=XYZ. Aleshores, es modificaria o.fooa o._$foo$XYZ_. Podeu canviar-ho cada vegada que compileu un script per identificar com s'ha alterat una propietat. Una tècnica és passar un nombre aleatori a cada compilació per simular el canvi de alteració amb diferents entrades (per exemple, a mesura que actualitzeu l'script d'entrada amb propietats noves) i per ajudar a identificar errors com escriure claus alterades a l'emmagatzematge.

Referència de l'API

Suposant la instal·lació mitjançant NPM, podeu carregar UglifyJS a la vostra aplicació així:

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

Hi ha una única funció d'alt nivell, minify(code, options), que realitzarà totes les fases de minificació d'una manera configurable. Per defecte minify()s'habilitaran les opcions compress i mangle. Exemple:

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}

Podeu fer minifymés d'un fitxer JavaScript alhora utilitzant un objecte per al primer argument on les claus són noms de fitxers i els valors són codi font:

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' toplevelopció:

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' nameCacheopció:

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

Podeu conservar la memòria cau de noms al sistema de fitxers de la manera següent:

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 exemple de combinació d' minify()opcions:

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 produir avisos:

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 exemple d'error:

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 diferència de uglify-js@2.x, l' 3.xAPI no genera errors. Per aconseguir un efecte similar, podeu fer el següent:

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

Reduïu les opcions

  • warnings(per defecte false) — passa trueper tornar els avisos del compressor a result.warnings. Utilitzeu el valor "verbose"per a avisos més detallats.

  • parse(per defecte {}): passeu un objecte si voleu especificar algunes opcions d'anàlisi addicionals .

  • compress(per defecte {}): passa falseper saltar la compressió completament. Passa un objecte per especificar opcions de compressió personalitzades .

  • mangle(per defecte true): passa falseper saltar els noms alterats, o passa un objecte per especificar opcions de manipulació (vegeu més avall).

    • mangle.properties(per defecte false): una subcategoria de l'opció de mangle. Passeu un objecte per especificar opcions de propietat de mangle personalitzades .
  • output(per defecte null): passa un objecte si vols especificar opcions de sortida addicionals . Els valors per defecte estan optimitzats per a la millor compressió.

  • sourceMap(per defecte false): passa un objecte si vols especificar les opcions del mapa font .

  • toplevel(per defecte false) - establiu-lo en truesi voleu habilitar la variable de nivell superior i la manipulació de noms de funció i eliminar les variables i funcions no utilitzades.

  • nameCache(per defecte null): passa un objecte buit {}o un objecte utilitzat anteriorment nameCachesi vols emmagatzemar a la memòria cau variables alterades i noms de propietats a través de diverses invocacions de minify(). Nota: aquesta és una propietat de lectura/escriptura. minify()llegirà l'estat de la memòria cau de noms d'aquest objecte i l'actualitzarà durant la minificació perquè l'usuari pugui reutilitzar-lo o persistir externament.

  • ie8(per defecte false): configurat per trueadmetre IE8.

  • keep_fnames(per defecte: false) - passa trueper evitar descartar o alterar els noms de funcions. Útil per al codi que es basa en Function.prototype.name.

Reduïu l'estructura d'opcions

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 generar un mapa font:

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

Tingueu en compte que el mapa font no es desa en un fitxer, només es retorna a result.map. El valor passat per sourceMap.urlnomés s'utilitza per establir //# sourceMappingURL=out.js.mapen result.code. El valor de filenamenomés s'utilitza per establir filel'atribut (vegeu l'especificació ) al fitxer de mapa font.

Podeu configurar l'opció sourceMap.urlper ser "inline"i el mapa font s'adjuntarà al codi.

També podeu especificar la propietat sourceRoot que s'inclou al mapa font:

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

Si esteu comprimint JavaScript compilat i teniu un mapa font, podeu utilitzar 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`

Si utilitzeu la X-SourceMapcapçalera, només podeu ometre sourceMap.url.

Anàlisi d'opcions

  • bare_returns(per defecte false) -- admet returndeclaracions de nivell superior

  • html5_comments(per defecte true)

  • shebang(per defecte true) -- suport #!commandcom a primera línia

Opcions de compressió

  • arguments(per defecte: true) -- substituïu arguments[index]amb el nom del paràmetre de funció sempre que sigui possible.

  • booleans(per defecte: true) -- diverses optimitzacions per al context booleà, per exemple!!a ? b : c → a ? b : c

  • collapse_vars(per defecte: true) -- Reduïu les variables no constants d'un sol ús, si els efectes secundaris ho permeten.

  • comparisons(per defecte: true) -- apliqueu certes optimitzacions als nodes binaris, per exemple !(a <= b) → a > b, els intents de negar nodes binaris, per exemple, a = !b && !c && !d && !e → a=!(b||c||d||e)etc.

  • conditionals(per defecte: true) -- aplica optimitzacions per a if-s i expressions condicionals

  • dead_code(per defecte: true) -- elimina el codi inabastable

  • drop_console(per defecte: false) -- Passeu trueper descartar les trucades a console.*funcions. Si voleu eliminar una trucada de funció específica, com ara console.infoi/o conservar els efectes secundaris dels arguments de funció després de deixar anar la trucada de funció, feu servir-lo pure_funcsen el seu lloc.

  • drop_debugger(per defecte: true) -- elimina debugger;declaracions

  • evaluate(per defecte: true) -- intenta avaluar expressions constants

  • expression(per defecte: false) -- Passeu trueper preservar els valors de finalització de les declaracions de terminal sense return, per exemple, als bookmarklets.

  • global_defs(per defecte: {}) -- vegeu la compilació condicional

  • hoist_funs(per defecte: false) -- declaracions de funció de polipast

  • hoist_props(per defecte: true) -- eleva les propietats d'objectes constants i literals de matriu a variables regulars subjectes a un conjunt de restriccions. Per exemple: var o={p:1, q:2}; f(o.p, o.q);es converteix a f(1, 2);. Nota: hoist_props funciona millor amb mangleenabled, l' compressopció passesestablerta a 2o superior i l' compressopció toplevelactivada.

  • hoist_vars(per defecte: false) -- vardeclaracions de polipast (això és false per defecte perquè sembla augmentar la mida de la sortida en general)

  • if_return(per defecte: true) -- optimitzacions per si/retorn i si/continua

  • inline(per defecte: true) -- crides en línia per funcionar amb returnla instrucció simple/:

    • false--el mateix que0
    • 0-- Inline desactivat
    • 1-- Funcions senzilles en línia
    • 2-- Funcions en línia amb arguments
    • 3-- Funcions en línia amb arguments i variables
    • true--el mateix que3
  • join_vars(per defecte: true) -- uneix vardeclaracions consecutives

  • keep_fargs(per defecte: true) -- Impedeix que el compressor descarti arguments de funció no utilitzats. Ho necessiteu per al codi que es basa en Function.length.

  • keep_fnames(per defecte: false) -- Passeu trueper evitar que el compressor descarti els noms de les funcions. Útil per al codi que es basa en Function.prototype.name. Vegeu també: l' keep_fnames opció de mangle .

  • keep_infinity(per defecte: false) -- Passa trueper evitar Infinityque es comprimeixi a 1/0, cosa que pot provocar problemes de rendiment a Chrome.

  • loops(per defecte: true) -- optimitzacions per a do, whilei forbucles quan podem determinar estàticament la condició.

  • negate_iife(per defecte: true) -- nega "Expressions de funció anomenades immediatament" on es descarta el valor de retorn, per evitar els paràmetres que inseriria el generador de codi.

  • passes(per defecte: 1) -- El nombre màxim de vegades que s'executa comprimir. En alguns casos, més d'una passada condueix a més codi comprimit. Tingues en compte que més passades trigaran més temps.

  • properties(per defecte: true) -- reescriu l'accés a la propietat utilitzant la notació de punts, per exemplefoo["bar"] → foo.bar

  • pure_funcs(per defecte: null) -- Podeu passar una matriu de noms i UglifyJS assumirà que aquestes funcions no produeixen efectes secundaris. PERILL: no comprovarà si el nom s'ha redefinit en l'abast. Un cas d'exemple aquí, per exemple. var q = Math.floor(a/b)Si la variable qés no s'utilitza en cap altre lloc, UglifyJS el deixarà caure, però encara conservarà el Math.floor(a/b), sense saber què fa. Podeu passar pure_funcs: [ 'Math.floor' ]per fer-li saber que aquesta funció no produirà cap efecte secundari, en aquest cas es descartaria tota la declaració. La implementació actual afegeix una mica de sobrecàrrega (la compressió serà més lenta). Assegureu-vos que els símbols de sota pure_funcs també estiguin sota mangle.reservedper evitar que es deformin.

  • pure_getters(per defecte: "strict") -- Si ho aproveu true, UglifyJS assumirà que l'accés a la propietat de l'objecte (p. ex. foo.baro foo["bar"]) no té cap efecte secundari. Especifiqueu "strict"per tractar foo.bar-lo com a sense efectes secundaris només quan fooestigui segur que no es llançarà, és a dir, no. nullo undefined.

  • reduce_funcs(per defecte: true) -- Permet que les funcions d'un sol ús s'incloguin com a expressions de funció quan es permet una optimització addicional. Habilitada de manera predeterminada. L'opció depèn d' reduce_vars estar habilitada. Alguns codis s'executen més ràpidament al motor Chrome V8 si aquesta opció està desactivada. No ho fa. impacte negativament en altres navegadors principals.

  • reduce_vars(per defecte: true) -- Millora l'optimització de les variables assignades i utilitzades com a valors constants.

  • sequences(per defecte: true) -- uneix declaracions simples consecutives mitjançant l'operador de coma. Es pot establir en un enter positiu per especificar el nombre màxim de seqüències de comes consecutives que es generaran. Si aquesta opció s'estableix en, trueel límit predeterminat sequencesés 200. Estableix l'opció desactivar falseo 0 desactivar. La sequenceslongitud més petita és 2. Un sequencesvalor de 1 s'assenyala per ser equivalent a truei com a tal significa 200. En rares ocasions, el límit de seqüències per defecte condueix a temps de compressió molt lents, en aquest cas 20es recomana un valor igual o inferior.

  • side_effects(per defecte: true) -- Passeu falseper desactivar les funcions que es poden eliminar marcades com a "pures". Una trucada de funció es marca com a "pura" si una anotació de comentari /*@__PURE__*/o /*#__PURE__*/precedeix immediatament la trucada. Per exemple:/*@__PURE__*/foo();

  • switches(per defecte: true) -- desduplica i elimina switchles branques inabastables

  • toplevel(per defecte: false) -- elimina les funcions sense referència ( "funcs") i/o variables ( "vars") a l'àmbit de nivell superior ( falseper defecte, trueelimina tant les funcions com les variables sense referència)

  • top_retain(per defecte: null) -- evita que s'eliminin funcions i variables de nivell superior específiques unused(pot ser matriu, separades per comes, ExpExp o funció. Implica toplevel)

  • typeofs(per defecte: true) -- Es transforma typeof foo == "undefined"en foo === void 0. Nota: es recomana establir aquest valor a falseper a IE10 i versions anteriors a causa de problemes coneguts.

  • unsafe(per defecte: false) -- apliqueu transformacions "no segures" (debat a continuació)

  • unsafe_comps(per defecte: false) -- comprimir expressions com a <= bassumir que cap dels operands pot ser (coaccionat a) NaN.

  • unsafe_Function(per defecte: false) -- comprimeix i manipula Function(args, code) quan tots dos argsi codesón literals de cadena.

  • unsafe_math(per defecte: false) -- optimitzeu expressions numèriques com 2 * x * 3en 6 * x, que poden donar resultats imprecisos en coma flotant.

  • unsafe_proto(per defecte: false) -- optimitza expressions com Array.prototype.slice.call(a)en[].slice.call(a)

  • unsafe_regexp(per defecte: false) -- permet les substitucions de variables amb RegExpvalors de la mateixa manera que si fossin constants.

  • unsafe_undefined(per defecte: false) -- substitueix void 0si hi ha una variable anomenada undefineda l'abast (el nom de la variable es modificarà, normalment es redueix a un sol caràcter)

  • unused(per defecte: true) -- elimina les funcions i variables sense referència (les assignacions simples de variables directes no compten com a referències tret que s'estableixin a "keep_assign")

  • warnings(per defecte: false) -- mostra advertències en deixar anar el codi inabastable o declaracions no utilitzades, etc.

Mangle opcions

  • eval(per defecte false) -- Passa truea mangle noms visibles als àmbits evalon withs'utilitzen o.

  • keep_fnames(per defecte false) -- Passeu trueper no manipular els noms de les funcions. Útil per al codi que es basa en Function.prototype.name. Vegeu també: l' keep_fnames opció de comprimir .

  • reserved(per defecte []) -- Passeu una matriu d'identificadors que s'han d'excloure de la manipulació. Exemple: ["foo", "bar"].

  • toplevel(per defecte false) -- Passa truea mangle els noms declarats a l'àmbit de nivell superior.

Exemples:

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(per defecte: false) -- S'utilitza trueper permetre la alteració de les propietats DOM integrades. No es recomana anul·lar aquesta configuració.

  • debug(per defecte: false) -- Manipula els noms amb el nom original encara present. Passa una cadena buida ""per activar-la o una cadena no buida per establir el sufix de depuració.

  • keep_quoted(per defecte: false) -- Manipula només els noms de propietats sense cometes.

  • regex(per defecte: null) -- Passeu un literal d'Exp Regual només per modificar els noms de propietats que coincideixen amb l'expressió regular.

  • reserved(per defecte: []) -- No modifiqueu els noms de propietat que figuren a la reservedmatriu.

Opcions de sortida

El generador de codi intenta generar el codi més curt possible de manera predeterminada. En cas que vulgueu una sortida embellida, passeu --beautify( -b). Opcionalment, podeu passar arguments addicionals que controlin la sortida del codi:

  • ascii_only(per defecte false) -- escapa els caràcters Unicode a les cadenes i les expressions regulars (afecta les directives amb caràcters no ascii que esdevenen invàlids)

  • beautify(per defecte true) -- si s'ha d'embellir realment la sortida. Passar- -bho establirà com a vertader, però és possible que hàgiu de passar -bfins i tot quan vulgueu generar codi minificat, per tal d'especificar arguments addicionals, de manera que podeu utilitzar-lo -b beautify=falseper anul·lar-lo.

  • braces(per defecte false) -- inseriu sempre claus en if, for, do, whileo withsentències, encara que el seu cos sigui una sola sentència.

  • comments(per defecte false) -- passa trueo "all"per conservar tots els comentaris, "some"per conservar alguns comentaris, una cadena d'expressió regular (p. ex. /^!/) o una funció.

  • indent_level(per defecte 4)

  • indent_start(per defecte 0) -- prefixeu totes les línies amb tants espais

  • inline_script(per defecte true) -- escapa dels comentaris HTML i de la barra inclinada en les ocurrències d' </script>in strings

  • keep_quoted_props(per defecte false) -- quan està activat, impedeix eliminar les cometes dels noms de propietats dels literals d'objectes.

  • max_line_len(per defecte false) -- longitud màxima de línia (per a codi llegit)

  • preamble(per defecte null) -- quan s'ha de passar ha de ser una cadena i s'adjuntarà literalment a la sortida. El mapa d'origen s'ajustarà per a aquest text. Es pot utilitzar per inserir un comentari que contingui informació de llicència, per exemple.

  • preserve_line(per defecte false) -- passa trueper conservar les línies, però només funciona si beautifys'estableix en false.

  • quote_keys(per defecte false) -- passa trueper citar totes les claus en objectes literals

  • quote_style(per defecte 0) -- l'estil de cometes preferit per a les cadenes (també afecta els noms de propietats i les directives citades):

    • 0-- prefereix cometes dobles, canvia a cometes simples quan hi ha més cometes dobles a la pròpia cadena. 0És millor per a la mida de gzip.
    • 1-- utilitzeu sempre cometes simples
    • 2-- utilitzeu sempre cometes dobles
    • 3-- utilitza sempre les cometes originals
  • semicolons(per defecte true) -- declaracions separades amb punt i coma. Si passeu, falsesempre que sigui possible, utilitzarem una nova línia en lloc d'un punt i coma, donant lloc a una sortida de codi llegible més llegible (la mida abans de gzip podria ser més petita; la mida després de gzip insignificantment més gran).

  • shebang(per defecte true) -- conserva shebang #!al preàmbul (scripts bash)

  • webkit(per defecte false) -- habiliteu solucions alternatives per als errors de WebKit. Els usuaris de PhantomJS haurien d'establir aquesta opció a true.

  • width(per defecte 80) -- només té efecte quan l'embelliment està activat, això especifica una amplada de línia (orientativa) que l'embellidor intentarà obeir. Es refereix a l'amplada del text de la línia (excepte el sagnat). No funciona gaire bé actualment, però fa que el codi generat per UglifyJS sigui més llegible.

  • wrap_iife(per defecte false) -- passa trueper embolicar les expressions de funció invocades immediatament. Vegeu #640 per a més detalls.

Divers

Podeu passar --commentsper retenir certs comentaris a la sortida. De manera predeterminada, mantindrà els comentaris d'estil JSDoc que continguin "@preserve", "@license" o "@cc_on" (compilació condicional per a IE). Podeu passar --comments allper mantenir tots els comentaris, o una expressió regular de JavaScript vàlida per conservar només els comentaris que coincideixin amb aquesta expressió regular. Per exemple, --comments /^!/ es mantindran comentaris com /*! Copyright Notice */.

Tingueu en compte, però, que hi pot haver situacions en què es perdin comentaris. Per exemple:

1 2 3 4 5 6 7
function f() { /** @preserve Foo Bar */ function g() { // this function is never called } return something(); }

Tot i que té "@preserve", el comentari es perdrà perquè la funció interna g(que és el node AST al qual s'adjunta el comentari) és descartada pel compressor com a no referenciada.

Els comentaris més segurs on col·locar la informació dels drets d'autor (o altra informació que s'ha de conservar a la sortida) són els comentaris adjunts als nodes de nivell superior.

L' unsafe compressopció

Permet algunes transformacions que poden trencar la lògica del codi en determinats casos artificials, però haurien d'estar bé per a la majoria del codi. És possible que vulgueu provar-ho amb el vostre propi codi, hauria de reduir la mida minificada. Això és el que passa quan aquesta marca està activada:

  • 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 (...)→ descartem elnew

Conditional compilation

Podeu utilitzar l' interruptor --define( -d) per declarar variables globals que UglifyJS suposarà que són constants (tret que es defineixin a l'abast). Per exemple, si ho passeu --define DEBUG=false, juntament amb l'eliminació del codi mort, UglifyJS descartarà el següent de la sortida:

1 2 3
if (DEBUG) { console.log("debug stuff"); }

Podeu especificar constants imbricades en forma de --define env.DEBUG=false.

UglifyJS advertirà que la condició és sempre falsa i que es deixa anar el codi inabastable; de ​​moment no hi ha cap opció per desactivar només aquest avís específic, podeu passar warnings=falseper desactivar tots els avisos.

Una altra manera de fer-ho és declarar els vostres globals com a constants en un fitxer separat i incloure-los a la compilació. Per exemple, podeu tenir un build/defines.jsfitxer amb el següent:

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

i construïu el vostre codi així:

1
uglifyjs build/defines.js js/foo.js js/bar.js... -c

UglifyJS notarà les constants i, com que no es poden alterar, avaluarà les referències a elles al valor en si i deixarà anar el codi inabastable com és habitual. La compilació contindrà les constdeclaracions si les feu servir. Si us orienteu a entorns < ES6 que no no és compatible const, varamb amb reduce_vars(activat per defecte) n'hi hauria prou.

Conditional compilation API

També podeu utilitzar la compilació condicional mitjançant l'API programàtica. Amb la diferència que el nom de la propietat és global_defsi és una propietat del compressor:

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 substituir un identificador per una expressió no constant arbitrària, cal prefixar la global_defsclau amb "@"per indicar a UglifyJS que analitzi el valor com a expressió:

1 2 3 4 5 6 7 8
UglifyJS.minify("alert('hello');", { compress: { global_defs: { "@alert": "console.log" } } }).code; // returns: 'console.log("hello");'

En cas contrari, es substituiria com a literal de cadena:

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

Utilitzant Uglify AST natiu ambminify()

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 transversal i la transformació de l'AST nadiu es poden realitzar mitjançant TreeWalkeri TreeTransformer respectivament.

ESTree / SpiderMonkey AST

L'UglifyJS té el seu propi format d'arbre de sintaxi abstracta; per raons pràctiques no podem canviar fàcilment a utilitzar l'AST de SpiderMonkey internament. Tanmateix, ara UglifyJS té un convertidor que pot importar un AST de SpiderMonkey.

Per exemple , Acorn és un analitzador súper ràpid que produeix un SpiderMonkey AST. Té una petita utilitat CLI que analitza un fitxer i aboca l'AST en JSON a la sortida estàndard. Per utilitzar UglifyJS per alterar i comprimir-ho:

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

L' -p spidermonkeyopció indica a UglifyJS que tots els fitxers d'entrada no són JavaScript, sinó codi JS descrit a SpiderMonkey AST en JSON. Per tant, no utilitzem el nostre propi analitzador en aquest cas, sinó que només transformem aquest AST en el nostre AST intern.

Use Acorn for parsing

Més per diversió, he afegit l' -p acornopció que utilitzarà Acorn per fer tota l'anàlisi. Si passeu aquesta opció, UglifyJS farà require("acorn").

Acorn és molt ràpid (per exemple, 250 ms en lloc de 380 ms en algun codi de 650 K), però convertir l'arbre SpiderMonkey que produeix Acorn triga 150 ms, de manera que en total és una mica més que utilitzar l'analitzador propi d'UglifyJS.

Uglify Fast Minify Mode

No és ben conegut, però l'eliminació d'espais en blanc i la manipulació de símbols representen el 95% de la reducció de la mida del codi minificat per a la majoria de les transformacions de codi JavaScript, no elaborades. Es pot desactivar simplement compressper accelerar les compilacions d'Uglify de 3 a 4 vegades mangle. L'únic mode Uglify té velocitats de minimització i mides de gzip comparables a butternut:

d3.js reduir la mida mida gzip reduir el temps (segons)
original 451.131 108.733 -
uglify-js@3.0.24 mangle=fals, comprimir=fals 316.600 85.245 0,70
uglify-js@3.0.24 mangle=true, comprimir=fals 220.216 72.730 1.13
butternut@0.4.6 217.568 72.738 1.41
uglify-js@3.0.24 mangle=true, comprimir=true 212.511 71.560 3.36
babili@0.1.4 210.713 72.140 12.64

Per habilitar el mode de minimització ràpida des de la CLI, feu servir:

1
uglifyjs file.js -m

Per habilitar el mode de minimització ràpida amb l'API, feu servir:

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

Mapes font i depuració

Se sap que diverses compresstransformacions que simplifiquen, reorganitzen, en línia i eliminen el codi tenen un efecte advers en la depuració amb mapes font. Això s'espera ja que el codi s'optimitza i sovint els mapes no són possibles perquè algun codi ja no existeix. Per a la màxima fidelitat a la font. la depuració de mapes desactiveu l'opció Uglify compressi només feu servir mangle.

Compiler assumptions

Per permetre millors optimitzacions, el compilador fa diversos supòsits:

  • .toString()i .valueOf()no tenen efectes secundaris, i per als objectes integrats no s'han anul·lat.
  • undefined, NaNi Infinityno s'han redefinit externament.
  • arguments.callee, arguments.calleri Function.prototype.callerno s'utilitzen.
  • El codi no espera que el contingut Function.prototype.toString()o Error.prototype.stacksigui res en particular.
  • Obtenir i establir propietats en un objecte senzill no provoca altres efectes secundaris (utilitzar .watch()o Proxy).
  • Les propietats de l'objecte es poden afegir, eliminar i modificar (no s'impedeix amb , Object.defineProperty(), Object.defineProperties()o ) .Object.freeze()Object.preventExtensions()Object.seal()