UgifyJS 3
UglifyJS é un analizador, minificador, compresor e ferramentas de embelecemento de JavaScript.
Nota:
uglify-js@3
ten unha API e unha CLI simplificadas que non son compatibles conuglify-js@2
.- A documentación para
2.x
as versións de UgliifyJS pódese atopar aquí . uglify-js
só admite JavaScript (ECMAScript 5).- Para minificar ECMAScript 2015 ou superior, transpile usando ferramentas como Babel .
Instalar
Primeiro asegúrate de ter instalada a última versión de node.js (é posible que teñas que reiniciar o teu ordenador despois deste paso).
Desde NPM para usar como aplicación de liña de comandos:
1npm install uglify-js -g
Desde NPM para uso programático:
1npm install uglify-js
Uso da liña de comandos
1uglifyjs [input files] [options]
UglifyJS pode tomar varios ficheiros de entrada. Recoméndase que pases primeiro os ficheiros de entrada e despois pases as opcións. UglifyJS analizará os ficheiros de entrada en secuencia e aplicará calquera opción de compresión. Os ficheiros analízanse no mesmo ámbito global, é dicir, unha referencia dun ficheiro a algunha variable/función declarada noutro ficheiro coincidirá correctamente.
Se non se especifica ningún ficheiro de entrada, UgliifyJS lerá desde STDIN.
Se queres pasar as túas opcións antes que os ficheiros de entrada, separa os dous cun guión dobre para evitar que os ficheiros de entrada se utilicen como argumentos de opción:
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.
Especifique --output
( -o
) para declarar o ficheiro de saída. Se non, a saída pasa a STDOUT.
Opcións do mapa fonte da CLI
UglifyJS pode xerar un ficheiro de mapa de orixe, que é moi útil para depurar o teu JavaScript comprimido. Para obter un mapa de orixe, pasa
--source-map --output output.js
(o mapa de orixe escribirase en
output.js.map
).
Opcións adicionais:
--source-map "filename='<NAME>'"
para especificar o nome do mapa de orixe.--source-map "root='<URL>'"
para pasar o URL onde se poden atopar os ficheiros orixinais.--source-map "url='<URL>'"
para especificar o URL onde se pode atopar o mapa de orixe. En caso contrario, UglifyJS asume queX-SourceMap
se está a usar HTTP e omitirá a//# sourceMappingURL=
directiva.
Por exemplo:
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'"
O anterior comprimirá e destrozará file1.js
e file2.js
, soltará a saída foo.min.js
e o mapa de orixe en foo.min.js.map
. A asignación de orixe farase referencia a http://foo.com/src/js/file1.js
e
http://foo.com/src/js/file2.js
(de feito listarase http://foo.com/src
como raíz do mapa de orixe e os ficheiros orixinais como js/file1.js
e
js/file2.js
).
Composed source map
Cando estás comprimindo código JS que saíu un compilador como CoffeeScript, a asignación ao código JS non será demasiado útil. Pola contra, queres volver a mapear o código orixinal (por exemplo, CoffeeScript). UglifyJS ten un opción para tomar un mapa de orixe de entrada. Asumindo que tes unha asignación de CoffeeScript → JS compilado, UglifyJS pode xerar un mapa desde CoffeeScript → JS comprimido asignando cada token do JS compilado á súa localización orixinal.
Para usar esta función pase --source-map "content='/path/to/input/source.map'"
ou --source-map "content=inline"
se o mapa de orixe está incluído en liña coas fontes.
Opcións de compresión da CLI
Debes pasar --compress
( -c
) para activar o compresor. Opcionalmente podes pasar unha lista de opcións de compresión separadas por comas .
As opcións están na forma foo=bar
, ou só foo
(esta última implica unha opción booleana que quere configurar true
; é efectivamente un atallo para foo=true
).
Exemplo:
1uglifyjs file.js -c toplevel,sequences=false
Opcións de mangle CLI
Para activar o mangler, cómpre pasar --mangle
( -m
). Admítense as seguintes opcións (separadas por comas):
toplevel
(predeterminadofalse
) -- destroza os nomes declarados no ámbito de nivel superior.eval
(predeterminadofalse
) -- destroza os nomes visibles nos ámbitos onde se usaeval
ou .with
Cando a manipulación está activada pero queres evitar que determinados nomes sexan destrozados, podes declarar eses nomes con --mangle reserved
— pase unha lista de nomes separados por comas. Por exemplo:
1uglifyjs ... -m reserved=['$','require','exports']
para evitar que se cambien os nomes require
, exports
e .$
CLI que modifica os nomes de propiedade ( --mangle-props
)
Nota: ESTE PROBABLEMENTE ROMPE O TEU CÓDIGO. A manipulación de nomes de propiedade é un paso separado, diferente da manipulación de nomes de variables. Pasa
--mangle-props
para activala. Destrozará todas as propiedades do código de entrada, a excepción das propiedades DOM integradas e as propiedades do JavaScript principal. clases. Por exemplo:
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());
Destruír todas as propiedades (excepto 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());
Destroza todas as propiedades excepto as reserved
propiedades:
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._());
Destroza todas as propiedades que coincidan con 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());
Opcións de combinación de propiedades 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());
Para que isto sexa útil, evitamos manipular os nomes JS estándar por defecto ( --mangle-props builtins
para anular).
Ofrécese un ficheiro de exclusión predeterminado no tools/domprops.json
que debería cubrir a maioría das propiedades estándar de JS e DOM definidas en varios navegadores. Pase
--mangle-props domprops
para desactivar esta función.
Pódese usar unha expresión regular para definir que nomes de propiedade deben ser alterados. Por exemplo, --mangle-props regex=/^_/
só se modificarán os nomes de propiedade que comecen cun guión baixo.
Cando comprimes varios ficheiros usando esta opción, para que funcionen xuntos ao final, debemos asegurarnos de que unha propiedade sexa alterada co mesmo nome en todos eles. Para iso, pass --name-cache filename.json
e UglifyJS manterá estas asignacións nun ficheiro que despois se pode reutilizar. Inicialmente debería estar baleiro. Exemplo:
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
Agora, part1.js
e part2.js
serán consistentes entre si en termos de nomes de propiedade mutilados.
Non é necesario usar a caché de nomes se comprimes todos os teus ficheiros nunha única chamada a UglifyJS.
Destrozando nomes sen comiñas ( --mangle-props keep_quoted
)
Usar o nome da propiedade entre comiñas ( o["foo"]
) reserva o nome da propiedade ( foo
) para que non se destrúe en todo o script aínda que se use nun estilo sen comiñas ( o.foo
). Exemplo:
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
Tamén podes pasar --mangle-props debug
para alterar os nomes das propiedades sen ocultalos por completo. Por exemplo, a propiedade o.foo
modificaríase o._$foo$_
con esta opción. Isto permite destrozar as propiedades dunha base de código grande, aínda que podes depurar o código e identificar onde se rompen as cousas.
1$ uglifyjs stuff.js --mangle-props debug -c -m
1var o={_$foo$_:1,_$bar$_:3};o._$foo$_+=o._$bar$_,console.log(o._$foo$_);
Tamén podes pasar un sufixo personalizado usando --mangle-props debug=XYZ
. Entón isto cambiaría o.foo
a o._$foo$XYZ_
. Podes cambialo cada vez que compiles un script para identificar como se destrozou unha propiedade. Unha técnica é pasar un número aleatorio a cada compilación para simular o cambio de alteración con diferentes entradas (por exemplo, mentres actualiza o script de entrada con novas propiedades) e para axudar a identificar erros como escribir chaves destrozadas no almacenamento.
Referencia da API
Asumindo a instalación mediante NPM, pode cargar UglifyJS na súa aplicación deste xeito:
1var UglifyJS = require("uglify-js");
Hai unha única función de alto nivel, minify(code, options)
, que realizará todas as fases de minificación dun xeito configurable. Por defecto minify()
activará as opcións compress
e mangle
. Exemplo:
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}
Podes minify
máis dun ficheiro JavaScript á vez usando un obxecto para o primeiro argumento onde as claves son nomes de ficheiros e os valores son código fonte:
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));
A toplevel
opción:
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);
A nameCache
opción:
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));
Pode conservar a caché de nomes no sistema de ficheiros do seguinte xeito:
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 exemplo dunha combinación de minify()
opcións:
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);"
Para producir 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 exemplo de erro:
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 diferenza de uglify-js@2.x
, a 3.x
API non xera erros. Para conseguir un efecto similar, pódese facer o seguinte:
1
2var result = UglifyJS.minify(code, options);
if (result.error) throw result.error;
Minimizar as opcións
warnings
(predeterminadofalse
) — pasetrue
para devolver avisos de compresor enresult.warnings
. Use o valor"verbose"
para avisos máis detallados.parse
(predeterminado{}
): pase un obxecto se quere especificar algunhas opcións de análise adicionais .compress
(predeterminado{}
): pasefalse
para omitir a compresión por completo. Pase un obxecto para especificar opcións de compresión personalizadas .mangle
(predeterminadotrue
): pasefalse
para omitir os nomes alterados ou pase un obxecto para especificar as opcións de destrozo (consulte a continuación).mangle.properties
(predeterminadofalse
) — unha subcategoría da opción de mangle. Pase un obxecto para especificar opcións de propiedade de mangle personalizadas .
output
(predeterminadonull
) — pasa un obxecto se queres especificar opcións de saída adicionais . Os valores predeterminados están optimizados para a mellor compresión.sourceMap
(predeterminadofalse
): pase un obxecto se desexa especificar as opcións do mapa de orixe .toplevel
(predeterminadofalse
) - establécesetrue
como se desexa activar a manipulación de nomes de funcións e variables de nivel superior e eliminar as variables e funcións non utilizadas.nameCache
(predeterminadonull
) - pase un obxecto baleiro{}
ou unnameCache
obxecto usado anteriormente se desexa almacenar na memoria caché os nomes de variables e propiedades alterados en varias invocacións deminify()
. Nota: esta é unha propiedade de lectura/escritura.minify()
lerá o estado da caché de nomes deste obxecto e actualizalo. durante a minificación para que o usuario poida reutilizalo ou persistir externamente.ie8
(predeterminadofalse
): configurado paratrue
admitir IE8.keep_fnames
(predeterminado:false
) - pasetrue
para evitar que se descarten ou destrúan os nomes das funcións. Útil para o código que depende deFunction.prototype.name
.
Minimizar a estrutura de opcións
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
Para xerar un mapa de orixe:
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
Teña en conta que o mapa de orixe non se garda nun ficheiro, só se devolve en
result.map
. O valor pasado sourceMap.url
só se usa para establecer
//# sourceMappingURL=out.js.map
en result.code
. O valor de
filename
só se usa para definir file
o atributo (consulte a especificación ) no ficheiro de mapa de orixe.
Podes configurar a opción sourceMap.url
para ser "inline"
e engadirase o mapa fonte ao código.
Tamén pode especificar a propiedade sourceRoot para incluír no mapa de orixe:
1
2
3
4
5
6var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, {
sourceMap: {
root: "http://example.com/src",
url: "out.js.map"
}
});
Se estás comprimindo JavaScript compilado e tes un mapa de orixe para el, podes usar sourceMap.content
:
1
2
3
4
5
6
7var result = UglifyJS.minify({"compiled.js": "compiled code"}, {
sourceMap: {
content: "content from compiled.js.map",
url: "minified.js.map"
}
});
// same as before, it returns `code` and `map`
Se estás usando a X-SourceMap
cabeceira no seu lugar, podes simplemente omitir sourceMap.url
.
Opcións de análise
bare_returns
(predeterminadofalse
) -- admitereturn
declaracións de nivel superiorhtml5_comments
(predeterminadotrue
)shebang
(predeterminadotrue
) -- soporte#!command
como primeira liña
Opcións de compresión
arguments
(predeterminado:true
) -- substituírarguments[index]
polo nome do parámetro da función sempre que sexa posible.booleans
(predeterminado:true
) -- varias optimizacións para o contexto booleano, por exemplo!!a ? b : c → a ? b : c
collapse_vars
(predeterminado:true
) -- Contraer variables non constantes dun só uso, se os efectos secundarios o permiten.comparisons
(predeterminado:true
) -- aplique certas optimizacións a nós binarios, por exemplo!(a <= b) → a > b
, intentos de negar nós binarios, por exemplo,a = !b && !c && !d && !e → a=!(b||c||d||e)
etc.conditionals
(predeterminado:true
) -- aplica optimizacións paraif
-s e expresións condicionaisdead_code
(predeterminado:true
) -- elimina o código inalcanzabledrop_console
(predeterminado:false
) -- Pasatrue
para descartar chamadas aconsole.*
funcións. Se queres eliminar unha chamada de función específica, comoconsole.info
e/ou conservar os efectos secundarios dos argumentos de función despois de soltar a chamada de función, úsaopure_funcs
no seu lugar.drop_debugger
(predeterminado:true
) -- eliminadebugger;
instruciónsevaluate
(predeterminado:true
) -- tenta avaliar expresións constantesexpression
(predeterminado:false
) -- Pasetrue
para preservar os valores de finalización das instrucións do terminal senreturn
, por exemplo, nos marcadores.global_defs
(predeterminado:{}
) -- consulte a compilación condicionalhoist_funs
(predeterminado:false
) -- declaracións da función de elevaciónhoist_props
(predeterminado:true
) -- eleva as propiedades de literais de obxectos e matrices constantes a variables normais suxeitas a un conxunto de restricións. Por exemplo:var o={p:1, q:2}; f(o.p, o.q);
convértese enf(1, 2);
. Nota:hoist_props
funciona mellor conmangle
enabled, acompress
opciónpasses
definida2
ou superior e acompress
opcióntoplevel
activada.hoist_vars
(predeterminado:false
) --var
declaracións de elevación (isto éfalse
por defecto porque parece aumentar o tamaño da saída en xeral)if_return
(predeterminado:true
) -- optimizacións para if/return e if/continueinline
(predeterminado:true
) -- chamadas en liña para funcionar conreturn
instrución simple/:false
--o mesmo que0
0
-- Inline desactivado1
-- funcións sinxelas en liña2
-- funcións en liña con argumentos3
-- funcións en liña con argumentos e variablestrue
--o mesmo que3
join_vars
(predeterminado: ) -- únete declaraciónstrue
consecutivasvar
keep_fargs
(predeterminado:true
) -- Evita que o compresor descarte argumentos de funcións non utilizados. Necesitas isto para o código que depende deFunction.length
.keep_fnames
(predeterminado:false
) -- Pasatrue
para evitar que o compresor descarte os nomes das funcións. Útil para que o código se basee enFunction.prototype.name
. Consulte tamén: akeep_fnames
opción de mangle .keep_infinity
(predeterminado:false
) -- Pasetrue
para evitarInfinity
que se comprima en1/0
, o que pode causar problemas de rendemento en Chrome.loops
(predeterminado:true
) -- optimizacións parado
,while
efor
bucles cando podemos determinar estáticamente a condición.negate_iife
(predeterminado:true
) -- nega "Expresións de función chamadas inmediatamente" onde se descarta o valor de retorno, para evitar os parénteses que inseriría o xerador de código.passes
(predeterminado:1
) -- O número máximo de veces para executar comprimir. Nalgúns casos, máis dunha pasada leva a un código comprimido máis. Ten en conta que máis pasadas levarán máis tempo.properties
(predeterminado:true
) -- reescribe o acceso á propiedade usando a notación de puntos, por exemplofoo["bar"] → foo.bar
pure_funcs
(predeterminado:null
) -- Podes pasar unha matriz de nomes e UglifyJS asumirá que esas funcións non producen efectos secundarios. PERIGO: non comprobará se o nome está redefinido no ámbito. Un exemplo de caso aquí, por exemplo.var q = Math.floor(a/b)
Se a variableq
é non se usa noutro lugar, UglifyJS abandonarao, pero aínda así manterá oMath.floor(a/b)
, sen saber o que fai. Podes pasarpure_funcs: [ 'Math.floor' ]
para informarlle de que esta función non producirá ningún efecto secundario, nese caso descartarase a declaración completa. a implementación actual engade algo de sobrecarga (a compresión será máis lenta). Asegúrate de que os símbolos debaixopure_funcs
tamén estean baixosmangle.reserved
para evitar destrozos.pure_getters
(predeterminado:"strict"
) -- Se pasatrue
por isto, UglifyJS asumirá que o acceso á propiedade do obxecto (por exemplo,foo.bar
oufoo["bar"]
) non ten ningún efecto secundario. Especifique"strict"
para tratarfoo.bar
como libre de efectos secundarios só candofoo
estea seguro de non lanzar, é dicir, nonnull
ouundefined
.reduce_funcs
(predeterminado:true
) -- Permite que as funcións dun só uso estean integradas como expresións de función cando se permite unha optimización adicional. Activada de forma predeterminada. A opción depende de quereduce_vars
estea activada. Algún código execútase máis rápido no motor Chrome V8 se esta opción está desactivada. Non o fai. afectan negativamente a outros navegadores principais.reduce_vars
(predeterminado:true
) -- Mellora a optimización das variables asignadas e utilizadas como valores constantes.sequences
(predeterminado:true
) -- une instrucións simples consecutivas mediante o operador de coma. Pódese establecer como un enteiro positivo para especificar o número máximo de secuencias de coma consecutivas que se xerarán. Se esta opción se define como límitetrue
predeterminadosequences
é200
. Establecer opción parafalse
ou0
para desactivar. Asequences
lonxitude máis pequena é2
. Unsequences
valor de1
é equivalente atrue
e como tal significa200
. En raras ocasións, o límite de secuencias predeterminados conduce a tempos de compresión moi lentos, caso en que20
se recomenda un valor igual ou inferior.side_effects
(predeterminado:true
) -- Pasarfalse
para desactivar funcións que se poden eliminar marcadas como "puras". Unha chamada de función márcase como "pura" se unha anotación de comentario/*@__PURE__*/
ou/*#__PURE__*/
precede inmediatamente á chamada. Por exemplo:/*@__PURE__*/foo();
switches
(predeterminado:true
) -- desduplica e eliminaswitch
ramas inalcanzablestoplevel
(predeterminado:false
) -- elimina funcións sen referencia ("funcs"
) e/ou variables ("vars"
) no ámbito de nivel superior (false
por defecto,true
elimina funcións e variables sen referencia)top_retain
(predeterminado:null
) -- evita que se eliminen funcións e variables específicas de nivel superiorunused
(pode ser matriz, separadas por comas, ExpExp ou función. Implicatoplevel
)typeofs
(predeterminado:true
) -- Transfórmasetypeof foo == "undefined"
enfoo === void 0
. Nota: recoméndase establecer este valorfalse
para IE10 e versións anteriores debido a problemas coñecidos.unsafe
(predeterminado:false
) -- aplicar transformacións "inseguras" (discusión a continuación)unsafe_comps
(predeterminado:false
) -- comprime expresións comoa <= b
asumir que ningún dos operandos pode ser (coaccionado a)NaN
.unsafe_Function
(predeterminado:false
) -- comprimir e destrozarFunction(args, code)
cando ambosargs
ecode
son literais de cadea.unsafe_math
(predeterminado:false
) -- optimiza expresións numéricas como2 * x * 3
into6 * x
, que pode dar resultados imprecisos en coma flotante.unsafe_proto
(predeterminado:false
) -- optimiza expresións comoArray.prototype.slice.call(a)
into[].slice.call(a)
unsafe_regexp
(predeterminado:false
) -- permite substitucións de variables conRegExp
valores do mesmo xeito que se fosen constantes.unsafe_undefined
(predeterminado:false
) -- substitúeovoid 0
se hai unha variable nomeadaundefined
no ámbito (o nome da variable será alterado, normalmente reducido a un só carácter)unused
(predeterminado:true
) -- elimina funcións e variables sen referencia (as asignacións de variables directas sinxelas non contan como referencias a menos que se establezan en"keep_assign"
)warnings
(predeterminado:false
) -- mostra avisos ao soltar código inalcanzable ou declaracións non utilizadas, etc.
Mangle opcións
eval
(predeterminadofalse
) -- Pasatrue
a destrozar os nomes visibles nos ámbitos onde se usaneval
ou .with
keep_fnames
(predeterminadofalse
) -- Pasetrue
para non alterar os nomes das funcións. Útil para o código baseado enFunction.prototype.name
. Consulte tamén: akeep_fnames
opción de comprimir .reserved
(predeterminado[]
) -- Pase unha matriz de identificadores que deberían excluírse da manipulación. Exemplo:["foo", "bar"]
.toplevel
(predeterminadofalse
) -- Pasatrue
a mangle os nomes declarados no ámbito de nivel superior.
Exemplos:
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
(predeterminado:false
) -- Utilízasetrue
para permitir a alteración das propiedades DOM integradas. Non se recomenda anular esta configuración.debug
(predeterminado:false
) -- Destroza os nomes co nome orixinal aínda presente. Pasa unha cadea baleira""
para activala ou unha cadea non baleira para establecer o sufixo de depuración.keep_quoted
(predeterminado:false
) -- Destroza só os nomes de propiedade sen comiñas.regex
(predeterminado:null
) -- Pase un literal de RegExp para modificar só os nomes de propiedade que coincidan coa expresión regular.reserved
(predeterminado:[]
) -- Non manipular os nomes das propiedades listados nareserved
matriz.
Opcións de saída
O xerador de código tenta producir o código máis curto posible de forma predeterminada. No caso de querer unha saída embelecida, pase --beautify
( -b
). Opcionalmente, pode pasar argumentos adicionais que controlen a saída do código:
ascii_only
(predeterminadofalse
) -- escape de caracteres Unicode en cadeas e expresións regulares (afecta ás directivas con caracteres non ascii que non son válidos)beautify
(predeterminadotrue
) -- se realmente embelece a saída. Ao pasar-b
isto establecerase como verdadeiro, pero pode que teñas que pasar-b
mesmo cando queiras xerar código minificado, para especificar argumentos adicionais, para que poidas utilizalo-b beautify=false
para anulalo.braces
(predeterminadofalse
) -- sempre insira chaves nas instruciónsif
,for
, ou , aínda que o seu corpo sexa unha única instrucióndo
.while
with
comments
(predeterminadofalse
) -- pasetrue
ou"all"
para conservar todos os comentarios,"some"
para conservar algúns comentarios, unha cadea de expresións regulares (por exemplo,/^!/
) ou unha función.indent_level
(predeterminado4
)indent_start
(predeterminado0
) -- prefixo todas as liñas con tantos espazosinline_script
(predeterminadotrue
) -- escape comentarios HTML e a barra inclinada nas ocorrencias de</script>
en cadeaskeep_quoted_props
(predeterminadofalse
) -- cando está activado, impide eliminar as comiñas dos nomes de propiedade nos literais de obxecto.max_line_len
(predeterminadofalse
) -- lonxitude máxima da liña (para o código feo)preamble
(predeterminadonull
) -- cando se pasa debe ser unha cadea e antepoñerase literalmente á saída. O mapa de orixe axustarase para este texto. Pódese usar para inserir un comentario que conteña información de licenza, por exemplo.preserve_line
(predeterminadofalse
) -- pasatrue
para conservar liñas, pero só funciona sebeautify
está configurado comofalse
.quote_keys
(predeterminadofalse
) -- pasetrue
para citar todas as claves en obxectos literaisquote_style
(predeterminado0
) -- estilo de comiña preferido para as cadeas (afecta tamén aos nomes e ás directivas das propiedades citadas):0
-- prefire comiñas dobres, cambia a comiñas simples cando hai máis comiñas dobres na propia cadea.0
é o mellor para o tamaño do gzip.1
-- use sempre comiñas simples2
-- use sempre comiñas dobres3
-- use sempre as comiñas orixinais
semicolons
(predeterminadotrue
) -- declaracións separadas con punto e coma. Se pasa,false
sempre que sexa posible, utilizaremos unha liña nova en lugar de punto e coma, o que dará lugar a unha saída máis lexible de código feo (o tamaño antes de gzip pode ser menor; o tamaño despois de gzip é insignificantemente maior).shebang
(predeterminadotrue
) -- conserva shebang#!
no preámbulo (scripts bash)webkit
(predeterminadofalse
) -- habilite as solucións para os erros de WebKit. Os usuarios de PhantomJS deben establecer esta opción entrue
.width
(predeterminado80
) -- só ten efecto cando o embelecemento está activado, isto especifica un ancho de liña (orientativo) que o embelecedor tentará obedecer. Refírese ao ancho do texto da liña (excluíndo a sangría). Non funciona moi ben actualmente, pero fai que o código xerado por UglifyJS sexa máis lexible.wrap_iife
(predeterminadofalse
) -- pasetrue
para envolver expresións de función invocadas inmediatamente. Consulte #640 para obter máis detalles.
Varios
Keeping copyright notices or other comments
Podes pasar --comments
para conservar certos comentarios na saída. Por defecto, manterá os comentarios de estilo JSDoc que conteñan "@preserve", "@license" ou "@cc_on" (compilación condicional para IE). Podes pasar
--comments all
para manter todos os comentarios ou unha expresión regular de JavaScript válida para manter só os comentarios que coincidan con esta expresión regular. Por exemplo, --comments /^!/
manterase comentarios como /*! Copyright Notice */
.
Teña en conta, non obstante, que pode haber situacións nas que se perdan comentarios. Por exemplo:
1
2
3
4
5
6
7function f() {
/** @preserve Foo Bar */
function g() {
// this function is never called
}
return something();
}
Aínda que teña "@preserve", o comentario perderase porque a función interna g
(que é o nodo AST ao que está conectado o comentario) é descartada polo compresor como non se fai referencia.
Os comentarios máis seguros onde colocar información de copyright (ou outra información que se debe gardar na saída) son os comentarios adxuntos aos nodos de nivel superior.
A unsafe
compress
opción
Permite algunhas transformacións que poden romper a lóxica do código nalgúns casos artificiais, pero deberían estar ben para a maioría do código. Quizais queiras probalo no teu propio código, debería reducir o tamaño reducido. Isto é o que ocorre cando esta marca está activada:
new Array(1, 2, 3)
ouArray(1, 2, 3)
→[ 1, 2, 3 ]
new Object()
→{}
String(exp)
ouexp.toString()
→"" + exp
new Object/RegExp/Function/Error/Array (...)
→ descartamos onew
Conditional compilation
Podes usar o interruptor --define
( -d
) para declarar as variables globais que UglifyJS asumirá como constantes (a non ser que se defina no ámbito). Por exemplo, se pasas --define DEBUG=false
entón, xunto coa eliminación do código morto, UglifyJS descartará o seguinte da saída:
1
2
3if (DEBUG) {
console.log("debug stuff");
}
Podes especificar constantes aniñadas en forma de --define env.DEBUG=false
.
UglifyJS avisará de que a condición é sempre falsa e de que se solta o código inalcanzable; polo momento non hai opción para desactivar só este aviso específico, pode pasar warnings=false
para desactivar todos os avisos.
Outra forma de facelo é declarar os teus globais como constantes nun ficheiro separado e incluílo na compilación. Por exemplo, podes ter un
build/defines.js
ficheiro co seguinte:
1
2
3var DEBUG = false;
var PRODUCTION = true;
// etc.
e crea o teu código así:
1uglifyjs build/defines.js js/foo.js js/bar.js... -c
UglifyJS notará as constantes e, dado que non se poden alterar, avaliará as referencias a elas co propio valor e deixará caer o código inalcanzable como é habitual. A compilación conterá as const
declaracións se as usas. Se estás dirixido a ambientes < ES6 que non not support const
, usar var
con reduce_vars
(activado por defecto) debería ser suficiente.
Conditional compilation API
Tamén podes usar a compilación condicional a través da API programática. Coa diferenza de que o nome da propiedade é global_defs
e é unha propiedade do compresor:
1
2
3
4
5
6
7
8var result = UglifyJS.minify(fs.readFileSync("input.js", "utf8"), {
compress: {
dead_code: true,
global_defs: {
DEBUG: false
}
}
});
Para substituír un identificador por unha expresión arbitraria non constante é necesario prefixar a global_defs
chave con "@"
para indicar a UglifyJS que analice o valor como expresión:
1
2
3
4
5
6
7
8UglifyJS.minify("alert('hello');", {
compress: {
global_defs: {
"@alert": "console.log"
}
}
}).code;
// returns: 'console.log("hello");'
En caso contrario, substituirase como literal de cadea:
1
2
3
4
5
6
7
8UglifyJS.minify("alert('hello');", {
compress: {
global_defs: {
"alert": "console.log"
}
}
}).code;
// returns: '"console.log"("hello");'
Usando 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
A transversal e a transformación da AST nativa pódense realizar mediante
TreeWalker
e
TreeTransformer
respectivamente.
ESTree / SpiderMonkey AST
UglifyJS ten o seu propio formato de árbore de sintaxe abstracta; por razóns prácticas non podemos cambiar facilmente a usar o SpiderMonkey AST internamente. Non obstante, UglifyJS ten agora un conversor que pode importar un SpiderMonkey AST.
Por exemplo , Acorn é un analizador súper rápido que produce un SpiderMonkey AST. Ten unha pequena utilidade CLI que analiza un ficheiro e volca o AST en JSON na saída estándar. Para usar UglifyJS para modificar e comprimir isto:
1acorn file.js | uglifyjs -p spidermonkey -m -c
A -p spidermonkey
opción indica a UglifyJS que todos os ficheiros de entrada non son JavaScript, senón código JS descrito en SpiderMonkey AST en JSON. Polo tanto, non usamos o noso propio analizador neste caso, senón que transformamos ese AST no noso AST interno.
Use Acorn for parsing
Máis por diversión, engadín a -p acorn
opción que usará Acorn para facer todo o análise. Se pasas esta opción, UgliifyJS fará require("acorn")
.
Acorn é moi rápido (por exemplo, 250 ms en lugar de 380 ms nalgún código de 650 K), pero converter a árbore SpiderMonkey que produce Acorn leva outros 150 ms, polo que en total é un pouco máis que usar o propio analizador de UglifyJS.
Uglify Fast Minify Mode
Non é moi coñecido, pero a eliminación de espazos en branco e a manipulación de símbolos representan o 95 % da redución de tamaño do código reducido para a maioría de JavaScript, non as transformacións de código elaboradas. Pódese simplemente desactivar compress
para acelerar as compilacións de Uglify de 3 a 4 veces. Desta forma rápida mangle
... O único modo Uglify ten velocidades de redución e tamaños gzip comparables a
butternut
:
d3.js | reducir o tamaño | tamaño gzip | tempo reducido (segundos) |
---|---|---|---|
orixinal | 451.131 | 108.733 | - |
uglify-js@3.0.24 mangle=falso, comprimir=falso | 316.600 | 85.245 | 0,70 |
uglify-js@3.0.24 mangle=true, comprimir=false | 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 |
Para activar o modo de minificación rápida desde a CLI, use:
1uglifyjs file.js -m
Para activar o modo de minificación rápida coa API, use:
1UglifyJS.minify(code, { compress: false, mangle: true });
Mapas de orixe e depuración
Sábese que varias compress
transformacións que simplifican, reorganizan, integran e eliminan código teñen un efecto adverso na depuración dos mapas fonte. Espérase que o código está optimizado e que moitas veces non son posibles as asignacións xa que algún código xa non existe. Para obter a máxima fidelidade na fonte. a depuración de mapas desactive a opción Uglify compress
e só use mangle
.
Compiler assumptions
Para permitir mellores optimizacións, o compilador fai varias suposicións:
.toString()
e.valueOf()
non teñen efectos secundarios, e para os obxectos incorporados non se anularon.undefined
,NaN
eInfinity
non se redefiniron externamente.arguments.callee
,arguments.caller
eFunction.prototype.caller
non se usan.- O código non espera que o contido
Function.prototype.toString()
ouError.prototype.stack
sexa algo en particular. - A obtención e configuración de propiedades nun obxecto simple non provoca outros efectos secundarios (usar
.watch()
ouProxy
). - As propiedades do obxecto pódense engadir, eliminar e modificar (non se evitan con
,
Object.defineProperty()
,Object.defineProperties()
ou ) .Object.freeze()
Object.preventExtensions()
Object.seal()