UglifyJS 3
UglifyJS és un conjunt d'eines d'analitzador, minificador, compressor i embellidor de JavaScript.
Nota:
uglify-js@3
té una API i una CLI simplificades que no són compatibles ambuglify-js@2
.- La documentació per a
2.x
les versions d'UglifyJS es pot trobar aquí . uglify-js
nomé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:
1npm install uglify-js -g
De NPM per a ús programàtic:
1npm install uglify-js
Ús de la línia d'ordres
1uglifyjs [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ó:
1uglifyjs --compress --mangle -- input.js
Command line options
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 -h, --help Print usage information.
`--help options` for details on available options.
-V, --version Print version number.
-p, --parse <options> Specify parser options:
`acorn` Use Acorn for parsing.
`bare_returns` Allow return outside of functions.
Useful when minifying CommonJS
modules and Userscripts that may
be anonymous function wrapped (IIFE)
by the .user.js engine `caller`.
`expression` Parse a single expression, rather than
a program (for parsing JSON).
`spidermonkey` Assume input files are SpiderMonkey
AST format (as JSON).
-c, --compress [options] Enable compressor/specify compressor options:
`pure_funcs` List of functions that can be safely
removed when their return values are
not used.
-m, --mangle [options] Mangle names/specify mangler options:
`reserved` List of names that should not be mangled.
--mangle-props [options] Mangle properties/specify mangler options:
`builtins` Mangle property names that overlaps
with standard JavaScript globals.
`debug` Add debug prefix and suffix.
`domprops` Mangle property names that overlaps
with DOM properties.
`keep_quoted` Only mangle unquoted properties.
`regex` Only mangle matched property names.
`reserved` List of names that should not be mangled.
-b, --beautify [options] Beautify output/specify output options:
`beautify` Enabled with `--beautify` by default.
`preamble` Preamble to prepend to the output. You
can use this to insert a comment, for
example for licensing information.
This will not be parsed, but the source
map will adjust for its presence.
`quote_style` Quote style:
0 - auto
1 - single
2 - double
3 - original
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
want to disable `negate_iife` under
compressor options.
-o, --output <file> Output file path (default STDOUT). Specify `ast` or
`spidermonkey` to write UglifyJS or SpiderMonkey AST
as JSON to STDOUT respectively.
--comments [filter] Preserve copyright comments in the output. By
default this works like Google Closure, keeping
JSDoc-style comments that contain "@license" or
"@preserve". You can optionally pass one of the
following arguments to this flag:
- "all" to keep all comments
- a valid JS RegExp like `/foo/` or `/^!/` to
keep only matching comments.
Note that currently not *all* comments can be
kept when compression is on, because of dead
code removal or cascading statements into
sequences.
--config-file <file> Read `minify()` options from JSON file.
-d, --define <expr>[=value] Global definitions.
--ie8 Support non-standard Internet Explorer 8.
Equivalent to setting `ie8: true` in `minify()`
for `compress`, `mangle` and `output` options.
By default UglifyJS will not try to be IE-proof.
--keep-fnames Do not mangle/drop function names. Useful for
code relying on Function.prototype.name.
--name-cache <file> File to hold mangled name mappings.
--self Build UglifyJS as a library (implies --wrap UglifyJS)
--source-map [options] Enable source map/specify source map options:
`base` Path to compute relative paths from input files.
`content` Input source map, useful if you're compressing
JS that was generated from some other original
code. Specify "inline" if the source map is
included within the sources.
`filename` Name and/or location of the output source.
`includeSources` Pass this flag if you want to include
the content of source files in the
source map as sourcesContent property.
`root` Path to the original source to be included in
the source map.
`url` If specified, path to the source map to append in
`//# sourceMappingURL`.
--timings Display operations run time on STDERR.
--toplevel Compress and/or mangle variables in top level scope.
--verbose Print diagnostic messages.
--warn Print warning messages.
--wrap <name> Embed everything in a big function, making the
“exports” and “global” variables available. You
need to pass an argument to this option to
specify the name that your module will take
when included in, say, a browser.
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 queX-SourceMap
s'està utilitzant HTTP i ometrà la//# sourceMappingURL=
directiva.
Per exemple:
1
2
3uglifyjs js/file1.js js/file2.js \
-o foo.min.js -c -m \
--source-map "root='http://foo.com/src',url='foo.min.js.map'"
L'anterior comprimirà i manipularà file1.js
i file2.js
, deixarà anar la sortida foo.min.js
i el mapa d'origen a foo.min.js.map
. El mapeig d'origen es referirà a http://foo.com/src/js/file1.js
i
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.js
a 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:
1uglifyjs 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 defectefalse
) -- modifica els noms declarats a l'àmbit de nivell superior.eval
(per defectefalse
) -- modifica els noms visibles als àmbits on s'utilitzeneval
o .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:
1uglifyjs ... -m reserved=['$','require','exports']
per evitar que els noms require
, exports
i $
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-props
per 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
1var 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 reserved
les propietats:
1$ uglifyjs example.js -c -m --mangle-props reserved=[foo_,bar_]
1var x={o:0,foo_:1,_:function(){return this.foo_+this.o}};x.bar_=2,x.o=3,console.log(x._());
Destrossa totes les propietats que coincideixen amb regex
:
1$ uglifyjs example.js -c -m --mangle-props regex=/_$/
1var x={o:0,_:1,calc:function(){return this._+this.o}};x.l=2,x.o=3,console.log(x.calc());
Opcions de combinació de propietats de mangle:
1$ uglifyjs example.js -c -m --mangle-props regex=/_$/,reserved=[bar_]
1var x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log(x.calc());
Perquè això sigui útil, evitem alterar els noms JS estàndard per defecte ( --mangle-props builtins
per substituir).
Es proporciona un fitxer d'exclusió predeterminat tools/domprops.json
que hauria de cobrir la majoria de propietats estàndard de JS i DOM definides en diversos navegadors. Passeu
--mangle-props domprops
per 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.js
i part2.js
seran 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
1var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
Debugging property name mangling
També podeu passar --mangle-props debug
per 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
1var 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.foo
a 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í:
1var 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
4var code = "function add(first, second) { return first + second; }";
var result = UglifyJS.minify(code);
console.log(result.error); // runtime error, or `undefined` if no error
console.log(result.code); // minified output: function add(n,d){return n+d}
Podeu fer minify
mé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
7var code = {
"file1.js": "function add(first, second) { return first + second; }",
"file2.js": "console.log(add(1 + 2, 3 + 4));"
};
var result = UglifyJS.minify(code);
console.log(result.code);
// function add(d,n){return d+n}console.log(add(3,7));
L' toplevel
opció:
1
2
3
4
5
6
7
8var code = {
"file1.js": "function add(first, second) { return first + second; }",
"file2.js": "console.log(add(1 + 2, 3 + 4));"
};
var options = { toplevel: true };
var result = UglifyJS.minify(code, options);
console.log(result.code);
// console.log(3+7);
L' nameCache
opció:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var options = {
mangle: {
toplevel: true,
},
nameCache: {}
};
var result1 = UglifyJS.minify({
"file1.js": "function add(first, second) { return first + second; }"
}, options);
var result2 = UglifyJS.minify({
"file2.js": "console.log(add(1 + 2, 3 + 4));"
}, options);
console.log(result1.code);
// function n(n,r){return n+r}
console.log(result2.code);
// console.log(n(3,7));
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
16var cacheFileName = "/tmp/cache.json";
var options = {
mangle: {
properties: true,
},
nameCache: JSON.parse(fs.readFileSync(cacheFileName, "utf8"))
};
fs.writeFileSync("part1.js", UglifyJS.minify({
"file1.js": fs.readFileSync("file1.js", "utf8"),
"file2.js": fs.readFileSync("file2.js", "utf8")
}, options).code, "utf8");
fs.writeFileSync("part2.js", UglifyJS.minify({
"file3.js": fs.readFileSync("file3.js", "utf8"),
"file4.js": fs.readFileSync("file4.js", "utf8")
}, options).code, "utf8");
fs.writeFileSync(cacheFileName, JSON.stringify(options.nameCache), "utf8");
Un 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
21var code = {
"file1.js": "function add(first, second) { return first + second; }",
"file2.js": "console.log(add(1 + 2, 3 + 4));"
};
var options = {
toplevel: true,
compress: {
global_defs: {
"@console.log": "alert"
},
passes: 2
},
output: {
beautify: false,
preamble: "/* uglified */"
}
};
var result = UglifyJS.minify(code, options);
console.log(result.code);
// /* uglified */
// alert(10);"
Per produir avisos:
1
2
3
4
5
6var code = "function f(){ var u; return 2 + 3; }";
var options = { warnings: true };
var result = UglifyJS.minify(code, options);
console.log(result.error); // runtime error, `undefined` in this case
console.log(result.warnings); // [ 'Dropping unused variable u [0:1,18]' ]
console.log(result.code); // function f(){return 5}
Un exemple d'error:
1
2
3var result = UglifyJS.minify({"foo.js" : "if (0) else console.log(1);"});
console.log(JSON.stringify(result.error));
// {"message":"Unexpected token: keyword (else)","filename":"foo.js","line":1,"col":7,"pos":7}
Nota: a diferència de uglify-js@2.x
, l' 3.x
API no genera errors. Per aconseguir un efecte similar, podeu fer el següent:
1
2var result = UglifyJS.minify(code, options);
if (result.error) throw result.error;
Reduïu les opcions
warnings
(per defectefalse
) — passatrue
per tornar els avisos del compressor aresult.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{}
): passafalse
per saltar la compressió completament. Passa un objecte per especificar opcions de compressió personalitzades .mangle
(per defectetrue
): passafalse
per saltar els noms alterats, o passa un objecte per especificar opcions de manipulació (vegeu més avall).mangle.properties
(per defectefalse
): una subcategoria de l'opció de mangle. Passeu un objecte per especificar opcions de propietat de mangle personalitzades .
output
(per defectenull
): passa un objecte si vols especificar opcions de sortida addicionals . Els valors per defecte estan optimitzats per a la millor compressió.sourceMap
(per defectefalse
): passa un objecte si vols especificar les opcions del mapa font .toplevel
(per defectefalse
) - establiu-lo entrue
si voleu habilitar la variable de nivell superior i la manipulació de noms de funció i eliminar les variables i funcions no utilitzades.nameCache
(per defectenull
): passa un objecte buit{}
o un objecte utilitzat anteriormentnameCache
si vols emmagatzemar a la memòria cau variables alterades i noms de propietats a través de diverses invocacions deminify()
. 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 defectefalse
): configurat pertrue
admetre IE8.keep_fnames
(per defecte:false
) - passatrue
per evitar descartar o alterar els noms de funcions. Útil per al codi que es basa enFunction.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
8var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, {
sourceMap: {
filename: "out.js",
url: "out.js.map"
}
});
console.log(result.code); // minified output
console.log(result.map); // source map
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.url
només s'utilitza per establir
//# sourceMappingURL=out.js.map
en result.code
. El valor de
filename
només s'utilitza per establir file
l'atribut (vegeu l'especificació ) al fitxer de mapa font.
Podeu configurar l'opció sourceMap.url
per 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
6var 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
7var result = UglifyJS.minify({"compiled.js": "compiled code"}, {
sourceMap: {
content: "content from compiled.js.map",
url: "minified.js.map"
}
});
// same as before, it returns `code` and `map`
Si utilitzeu la X-SourceMap
capçalera, només podeu ometre sourceMap.url
.
Anàlisi d'opcions
bare_returns
(per defectefalse
) -- admetreturn
declaracions de nivell superiorhtml5_comments
(per defectetrue
)shebang
(per defectetrue
) -- suport#!command
com a primera línia
Opcions de compressió
arguments
(per defecte:true
) -- substituïuarguments[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 aif
-s i expressions condicionalsdead_code
(per defecte:true
) -- elimina el codi inabastabledrop_console
(per defecte:false
) -- Passeutrue
per descartar les trucades aconsole.*
funcions. Si voleu eliminar una trucada de funció específica, com araconsole.info
i/o conservar els efectes secundaris dels arguments de funció després de deixar anar la trucada de funció, feu servir-lopure_funcs
en el seu lloc.drop_debugger
(per defecte:true
) -- eliminadebugger;
declaracionsevaluate
(per defecte:true
) -- intenta avaluar expressions constantsexpression
(per defecte:false
) -- Passeutrue
per preservar els valors de finalització de les declaracions de terminal sensereturn
, per exemple, als bookmarklets.global_defs
(per defecte:{}
) -- vegeu la compilació condicionalhoist_funs
(per defecte:false
) -- declaracions de funció de polipasthoist_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 af(1, 2);
. Nota:hoist_props
funciona millor ambmangle
enabled, l'compress
opciópasses
establerta a2
o superior i l'compress
opciótoplevel
activada.hoist_vars
(per defecte:false
) --var
declaracions de polipast (això ésfalse
per defecte perquè sembla augmentar la mida de la sortida en general)if_return
(per defecte:true
) -- optimitzacions per si/retorn i si/continuainline
(per defecte:true
) -- crides en línia per funcionar ambreturn
la instrucció simple/:false
--el mateix que0
0
-- Inline desactivat1
-- Funcions senzilles en línia2
-- Funcions en línia amb arguments3
-- Funcions en línia amb arguments i variablestrue
--el mateix que3
join_vars
(per defecte:true
) -- uneixvar
declaracions consecutiveskeep_fargs
(per defecte:true
) -- Impedeix que el compressor descarti arguments de funció no utilitzats. Ho necessiteu per al codi que es basa enFunction.length
.keep_fnames
(per defecte:false
) -- Passeutrue
per evitar que el compressor descarti els noms de les funcions. Útil per al codi que es basa enFunction.prototype.name
. Vegeu també: l'keep_fnames
opció de mangle .keep_infinity
(per defecte:false
) -- Passatrue
per evitarInfinity
que es comprimeixi a1/0
, cosa que pot provocar problemes de rendiment a Chrome.loops
(per defecte:true
) -- optimitzacions per ado
,while
ifor
bucles 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 variableq
és no s'utilitza en cap altre lloc, UglifyJS el deixarà caure, però encara conservarà elMath.floor(a/b)
, sense saber què fa. Podeu passarpure_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 sotapure_funcs
també estiguin sotamangle.reserved
per evitar que es deformin.pure_getters
(per defecte:"strict"
) -- Si ho aproveutrue
, UglifyJS assumirà que l'accés a la propietat de l'objecte (p. ex.foo.bar
ofoo["bar"]
) no té cap efecte secundari. Especifiqueu"strict"
per tractarfoo.bar
-lo com a sense efectes secundaris només quanfoo
estigui segur que no es llançarà, és a dir, no.null
oundefined
.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,true
el límit predeterminatsequences
és200
. Estableix l'opció desactivarfalse
o0
desactivar. Lasequences
longitud més petita és2
. Unsequences
valor de1
s'assenyala per ser equivalent atrue
i com a tal significa200
. En rares ocasions, el límit de seqüències per defecte condueix a temps de compressió molt lents, en aquest cas20
es recomana un valor igual o inferior.side_effects
(per defecte:true
) -- Passeufalse
per 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 eliminaswitch
les branques inabastablestoplevel
(per defecte:false
) -- elimina les funcions sense referència ("funcs"
) i/o variables ("vars"
) a l'àmbit de nivell superior (false
per defecte,true
elimina 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ífiquesunused
(pot ser matriu, separades per comes, ExpExp o funció. Implicatoplevel
)typeofs
(per defecte:true
) -- Es transformatypeof foo == "undefined"
enfoo === void 0
. Nota: es recomana establir aquest valor afalse
per 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 coma <= b
assumir que cap dels operands pot ser (coaccionat a)NaN
.unsafe_Function
(per defecte:false
) -- comprimeix i manipulaFunction(args, code)
quan tots dosargs
icode
són literals de cadena.unsafe_math
(per defecte:false
) -- optimitzeu expressions numèriques com2 * x * 3
en6 * x
, que poden donar resultats imprecisos en coma flotant.unsafe_proto
(per defecte:false
) -- optimitza expressions comArray.prototype.slice.call(a)
en[].slice.call(a)
unsafe_regexp
(per defecte:false
) -- permet les substitucions de variables ambRegExp
valors de la mateixa manera que si fossin constants.unsafe_undefined
(per defecte:false
) -- substitueixvoid 0
si hi ha una variable anomenadaundefined
a 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 defectefalse
) -- Passatrue
a mangle noms visibles als àmbitseval
onwith
s'utilitzen o.keep_fnames
(per defectefalse
) -- Passeutrue
per no manipular els noms de les funcions. Útil per al codi que es basa enFunction.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 defectefalse
) -- Passatrue
a 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
10var code = fs.readFileSync("test.js", "utf8");
UglifyJS.minify(code).code;
// 'function funcName(a,n){}var globalVar;'
UglifyJS.minify(code, { mangle: { reserved: ['firstLongName'] } }).code;
// 'function funcName(firstLongName,a){}var globalVar;'
UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
// 'function n(n,a){}var a;'
Mangle properties options
builtins
(per defecte:false
) -- S'utilitzatrue
per 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 lareserved
matriu.
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 defectefalse
) -- 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 defectetrue
) -- si s'ha d'embellir realment la sortida. Passar--b
ho establirà com a vertader, però és possible que hàgiu de passar-b
fins i tot quan vulgueu generar codi minificat, per tal d'especificar arguments addicionals, de manera que podeu utilitzar-lo-b beautify=false
per anul·lar-lo.braces
(per defectefalse
) -- inseriu sempre claus enif
,for
,do
,while
owith
sentències, encara que el seu cos sigui una sola sentència.comments
(per defectefalse
) -- passatrue
o"all"
per conservar tots els comentaris,"some"
per conservar alguns comentaris, una cadena d'expressió regular (p. ex./^!/
) o una funció.indent_level
(per defecte4
)indent_start
(per defecte0
) -- prefixeu totes les línies amb tants espaisinline_script
(per defectetrue
) -- escapa dels comentaris HTML i de la barra inclinada en les ocurrències d'</script>
in stringskeep_quoted_props
(per defectefalse
) -- quan està activat, impedeix eliminar les cometes dels noms de propietats dels literals d'objectes.max_line_len
(per defectefalse
) -- longitud màxima de línia (per a codi llegit)preamble
(per defectenull
) -- 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 defectefalse
) -- passatrue
per conservar les línies, però només funciona sibeautify
s'estableix enfalse
.quote_keys
(per defectefalse
) -- passatrue
per citar totes les claus en objectes literalsquote_style
(per defecte0
) -- 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 simples2
-- utilitzeu sempre cometes dobles3
-- utilitza sempre les cometes originals
semicolons
(per defectetrue
) -- declaracions separades amb punt i coma. Si passeu,false
sempre 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 defectetrue
) -- conserva shebang#!
al preàmbul (scripts bash)webkit
(per defectefalse
) -- habiliteu solucions alternatives per als errors de WebKit. Els usuaris de PhantomJS haurien d'establir aquesta opció atrue
.width
(per defecte80
) -- 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 defectefalse
) -- passatrue
per embolicar les expressions de funció invocades immediatament. Vegeu #640 per a més detalls.
Divers
Keeping copyright notices or other comments
Podeu passar --comments
per 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 all
per 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
7function 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
compress
opció
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)
oArray(1, 2, 3)
→[ 1, 2, 3 ]
new Object()
→{}
String(exp)
oexp.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
3if (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=false
per 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.js
fitxer amb el següent:
1
2
3var DEBUG = false;
var PRODUCTION = true;
// etc.
i construïu el vostre codi així:
1uglifyjs 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 const
declaracions si les feu servir. Si us orienteu a entorns < ES6 que no no és compatible const
, var
amb 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_defs
i és una propietat del compressor:
1
2
3
4
5
6
7
8var result = UglifyJS.minify(fs.readFileSync("input.js", "utf8"), {
compress: {
dead_code: true,
global_defs: {
DEBUG: false
}
}
});
Per substituir un identificador per una expressió no constant arbitrària, cal prefixar la global_defs
clau amb "@"
per indicar a UglifyJS que analitzi el valor com a expressió:
1
2
3
4
5
6
7
8UglifyJS.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
8UglifyJS.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
TreeWalker
i
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:
1acorn file.js | uglifyjs -p spidermonkey -m -c
L' -p spidermonkey
opció 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 acorn
opció 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 compress
per 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:
1uglifyjs file.js -m
Per habilitar el mode de minimització ràpida amb l'API, feu servir:
1UglifyJS.minify(code, { compress: false, mangle: true });
Mapes font i depuració
Se sap que diverses compress
transformacions 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 compress
i 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
,NaN
iInfinity
no s'han redefinit externament.arguments.callee
,arguments.caller
iFunction.prototype.caller
no s'utilitzen.- El codi no espera que el contingut
Function.prototype.toString()
oError.prototype.stack
sigui res en particular. - Obtenir i establir propietats en un objecte senzill no provoca altres efectes secundaris (utilitzar
.watch()
oProxy
). - 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()