UglifyJS 3
UglifyJS es un conjunto de herramientas de analizador, minificador, compresor y embellecedor de JavaScript.
Nota:
uglify-js@3
tiene una API y una CLI simplificadas que no son compatibles con versiones anteriores deuglify-js@2
.- La documentación para
2.x
las versiones de UglifyJS se puede encontrar aquí . uglify-js
solo admite JavaScript (ECMAScript 5).- Para minimizar ECMAScript 2015 o superior, transpile usando herramientas como Babel .
Instalar
Primero asegúrese de haber instalado la última versión de node.js (es posible que deba reiniciar su computadora después de este paso).
Desde NPM para usar como aplicación de línea de comandos:
1npm install uglify-js -g
De NPM para uso programático:
1npm install uglify-js
Uso de la línea de comando
1uglifyjs [input files] [options]
UglifyJS puede tomar varios archivos de entrada. Se recomienda pasar primero los archivos de entrada y luego pasar las opciones. UglifyJS analizará los archivos de entrada en secuencia y aplicará cualquier opción de compresión. Los archivos se analizan en el mismo ámbito global, es decir, una referencia de un archivo a alguna variable/función declarada en otro archivo coincidirá correctamente.
Si no se especifica ningún archivo de entrada, UglifyJS leerá desde STDIN.
Si desea pasar sus opciones antes de los archivos de entrada, separe los dos con un guión doble para evitar que los archivos de entrada se utilicen como argumentos de opciones:
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 el archivo de salida. De lo contrario, la salida va a STDOUT.
Opciones de mapa de origen CLI
UglifyJS puede generar un archivo de mapa fuente, lo cual es muy útil para depurar su JavaScript comprimido. Para obtener un mapa fuente, pase
--source-map --output output.js
(el mapa fuente se escribirá en
output.js.map
).
Opciones adicionales:
--source-map "filename='<NAME>'"
para especificar el nombre del mapa de origen.--source-map "root='<URL>'"
para pasar la URL donde se pueden encontrar los archivos originales.--source-map "url='<URL>'"
para especificar la URL donde se puede encontrar el mapa fuente. De lo contrario, UglifyJS asume queX-SourceMap
se está utilizando HTTP y omitirá la//# sourceMappingURL=
directiva.
Por ejemplo:
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'"
Lo anterior comprimirá y destrozará file1.js
y file2.js
colocará la salida en foo.min.js
y el mapa de origen en foo.min.js.map
. El mapeo de origen hará referencia a http://foo.com/src/js/file1.js
y
http://foo.com/src/js/file2.js
(de hecho, aparecerá http://foo.com/src
como la raíz del mapa de origen y los archivos originales como js/file1.js
y
js/file2.js
).
Composed source map
Cuando estás comprimiendo código JS generado por un compilador como CoffeeScript, el mapeo al código JS no será muy útil. En su lugar, te gustaría volver a mapearlo al código original (es decir, CoffeeScript). opción para tomar un mapa de fuente de entrada. Suponiendo que tiene un mapeo de CoffeeScript → JS compilado, UglifyJS puede generar un mapa de CoffeeScript → JS comprimido asignando cada token en el JS compilado a su ubicación original.
Para utilizar esta función, pase --source-map "content='/path/to/input/source.map'"
o --source-map "content=inline"
si el mapa fuente se incluye en línea con las fuentes.
Opciones de compresión CLI
Debe pasar --compress
( -c
) para habilitar el compresor. Opcionalmente, puede pasar una lista de opciones de compresión separadas por comas .
Las opciones tienen el formato foo=bar
, o simplemente foo
(esta última implica una opción booleana que desea configurar true
; en realidad es un atajo para foo=true
).
Ejemplo:
1uglifyjs file.js -c toplevel,sequences=false
Opciones de manipulación CLI
Para habilitar el destructor, debe pasar --mangle
( -m
). Se admiten las siguientes opciones (separadas por comas):
toplevel
(predeterminadofalse
): modifica los nombres declarados en el ámbito de nivel superior.eval
(predeterminadofalse
): modifica los nombres visibles en los ámbitos donde se utilizaneval
o .with
Cuando la manipulación está habilitada pero desea evitar que ciertos nombres sean alterados, puede declarar esos nombres con --mangle reserved
— pasar una lista de nombres separados por comas. Por ejemplo:
1uglifyjs ... -m reserved=['$','require','exports']
para evitar que se cambien los require
nombres y exports
.$
CLI que modifica los nombres de propiedades ( --mangle-props
)
Nota: ESTO PROBABLEMENTE ROMPERÁ TU CÓDIGO. La alteración de los nombres de propiedades es un paso separado, diferente de la alteración de los nombres de las variables. Pase
--mangle-props
para habilitarlo. Destrozará todas las propiedades en el código de entrada con la excepción de las propiedades DOM integradas y las propiedades en el núcleo de JavaScript. clases Por ejemplo:
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());
Destroza todas las 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 las propiedades excepto las 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 las 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());
Combinando opciones 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 esto sea de alguna utilidad, evitamos alterar los nombres JS estándar de forma predeterminada ( --mangle-props builtins
para anular).
Se proporciona un archivo de exclusión predeterminado tools/domprops.json
que debería cubrir la mayoría de las propiedades JS y DOM estándar definidas en varios navegadores. Pase
--mangle-props domprops
para deshabilitar esta característica.
Se puede utilizar una expresión regular para definir qué nombres de propiedades deben modificarse. Por ejemplo, --mangle-props regex=/^_/
solo se modificarán los nombres de propiedades que comiencen con un guión bajo.
Cuando comprimes varios archivos usando esta opción, para que funcionen juntos al final necesitamos asegurarnos de alguna manera de que una propiedad se modifique con el mismo nombre en todos ellos. Para esto, pasa --name-cache filename.json
y UglifyJS mantendrá estas asignaciones en un archivo que luego puede ser reutilizado. Inicialmente debe estar vacío. Ejemplo:
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
Ahora, part1.js
y part2.js
serán coherentes entre sí en términos de nombres de propiedades alterados.
No es necesario usar el caché de nombres si comprime todos sus archivos en una sola llamada a UglifyJS.
Manipulación de nombres sin comillas ( --mangle-props keep_quoted
)
El uso del nombre de propiedad entre comillas ( o["foo"]
) reserva el nombre de la propiedad ( foo
) para que no se altere en todo el script, incluso cuando se usa en un estilo sin comillas ( o.foo
).
1
2
3
4
5
6
7// stuff.js
var o = {
"foo": 1,
bar: 3
};
o.foo += o.bar;
console.log(o.foo);
1$ uglifyjs stuff.js --mangle-props keep_quoted -c -m
1var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
Debugging property name mangling
También puede pasar --mangle-props debug
para alterar los nombres de las propiedades sin oscurecerlos por completo. Por ejemplo, la propiedad o.foo
se alteraría o._$foo$_
con esta opción. Esto permite alterar las propiedades de una base de código grande y al mismo tiempo poder depurar el código e identificar dónde la alteración está rompiendo las cosas.
1$ uglifyjs stuff.js --mangle-props debug -c -m
1var o={_$foo$_:1,_$bar$_:3};o._$foo$_+=o._$bar$_,console.log(o._$foo$_);
También puede pasar un sufijo personalizado usando --mangle-props debug=XYZ
. Esto luego se alteraría o.foo
a o._$foo$XYZ_
. Puede cambiar esto cada vez que compila un script para identificar cómo se alteró una propiedad. Una técnica es pasar un número aleatorio en cada compilación para simular el cambio de alteración con diferentes entradas (por ejemplo, a medida que actualiza el script de entrada con nuevas propiedades) y para ayudar a identificar errores como escribir claves alteradas en el almacenamiento.
Referencia de API
Suponiendo la instalación a través de NPM, puede cargar UglifyJS en su aplicación de esta manera:
1var UglifyJS = require("uglify-js");
Existe una única función de alto nivel, minify(code, options)
, que realizará todas las fases de minificación de forma configurable. Por defecto minify()
habilitará las opciones compress
y mangle
. Ejemplo:
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}
Puede tener minify
más de un archivo JavaScript a la vez usando un objeto para el primer argumento donde las claves son nombres de archivos y los valores son código fuente:
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));
La 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);
La 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));
Puede conservar el caché de nombres en el sistema de archivos de la siguiente manera:
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 ejemplo de una combinación de minify()
opciones:
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 advertencias:
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 ejemplo de 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 diferencia de uglify-js@2.x
, la 3.x
API no arroja errores. Para lograr un efecto similar se podría hacer lo siguiente:
1
2var result = UglifyJS.minify(code, options);
if (result.error) throw result.error;
Minimizar opciones
warnings
(predeterminadofalse
): pasatrue
para devolver las advertencias del compresor enresult.warnings
Utilice el valor"verbose"
para advertencias más detalladas.parse
(predeterminado{}
): pase un objeto si desea especificar algunas opciones de análisis adicionales .compress
(predeterminado{}
): pasefalse
para omitir la compresión por completo. Pase un objeto para especificar opciones de compresión personalizadas .mangle
(predeterminadotrue
): pasefalse
para omitir nombres de manipulación o pase un objeto para especificar opciones de manipulación (ver más abajo).mangle.properties
(predeterminadofalse
): una subcategoría de la opción de mangle. Pase un objeto para especificar opciones de propiedad de mangle personalizadas .
output
(predeterminadonull
): pase un objeto si desea especificar opciones de salida adicionales . Los valores predeterminados están optimizados para una mejor compresión.sourceMap
(predeterminadofalse
): pase un objeto si desea especificar opciones del mapa de origen .toplevel
(predeterminadofalse
): configúrelotrue
si desea habilitar la modificación de nombres de funciones y variables de nivel superior y eliminar variables y funciones no utilizadas.nameCache
(predeterminadonull
): pase un objeto vacío{}
o unnameCache
objeto utilizado anteriormente si desea almacenar en caché los nombres de variables y propiedades alteradas en múltiples invocaciones deminify()
. Nota: esta es una propiedad de lectura/escritura.minify()
Leerá el estado de la caché de nombres de este objeto y lo actualizará. durante la minificación para que el usuario pueda reutilizarlo o conservarlo externamente.ie8
(predeterminadofalse
): configurado paratrue
admitir IE8.keep_fnames
(predeterminado:false
): pasatrue
para evitar el descarte o la alteración de nombres de funciones. Útil para código que depende deFunction.prototype.name
.
Minimizar estructura de opciones
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 generar un mapa fuente:
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
Tenga en cuenta que el mapa de origen no se guarda en un archivo, simplemente se devuelve en
result.map
. El valor pasado sourceMap.url
solo se usa para establecer
//# sourceMappingURL=out.js.map
en result.code
. El valor de
filename
solo se usa para establecer file
el atributo (consulte la especificación ) en el archivo de mapa de origen.
Puede configurar la opción sourceMap.url
para que sea "inline"
y el mapa fuente se agregará al código.
También puede especificar la propiedad sourceRoot para que se incluya en el mapa fuente:
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 está comprimiendo JavaScript compilado y tiene un mapa fuente para él, puede 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`
Si en su lugar estás usando el X-SourceMap
encabezado, puedes simplemente omitirlo sourceMap.url
.
Opciones de análisis
bare_returns
(predeterminadofalse
): admitereturn
declaraciones de nivel superiorhtml5_comments
(por defectotrue
)shebang
(predeterminadotrue
): soporte#!command
como primera línea
Opciones de compresión
arguments
(predeterminadotrue
:): reempláceloarguments[index]
con el nombre del parámetro de función siempre que sea posible.booleans
(predeterminado:)true
- varias optimizaciones para el contexto booleano, por ejemplo!!a ? b : c → a ? b : c
collapse_vars
(predeterminado:true
): contrae las variables no constantes de un solo uso, si los efectos secundarios lo permiten.comparisons
(predeterminado:)true
: aplica ciertas optimizaciones a los nodos binarios, por ejemplo!(a <= b) → a > b
, intenta negar nodos binarios, por ejemplo,a = !b && !c && !d && !e → a=!(b||c||d||e)
etc.conditionals
(predeterminado:):true
aplica optimizaciones paraif
-s y expresiones condicionalesdead_code
(predeterminado:true
): elimina el código inalcanzabledrop_console
(predeterminado:false
) -- Pasartrue
para descartar llamadas aconsole.*
funciones. Si desea descartar una llamada de función específica, comoconsole.info
y/o conservar los efectos secundarios de los argumentos de la función después de descartar la llamada de función, utilicepure_funcs
en su lugar.drop_debugger
(predeterminado:true
) -- eliminardebugger;
declaracionesevaluate
(predeterminado:true
) -- intenta evaluar expresiones constantesexpression
(predeterminado:):false
pasetrue
para conservar los valores de finalización de las declaraciones del terminal sinreturn
, por ejemplo, en los marcadores.global_defs
(predeterminado:{}
) - ver compilación condicionalhoist_funs
(predeterminado:false
) -- declaraciones de función de elevaciónhoist_props
(predeterminado:true
): eleva las propiedades de objetos constantes y literales de matriz a variables regulares sujetas a un conjunto de restricciones. Por ejemplo:var o={p:1, q:2}; f(o.p, o.q);
se convierte af(1, 2);
. Nota:hoist_props
funciona mejor conmangle
habilitado, lacompress
opciónpasses
establecida en2
o superior y lacompress
opcióntoplevel
habilitada.hoist_vars
(predeterminado:false
) --var
declaraciones de elevación (esto esfalse
predeterminado porque parece aumentar el tamaño de la salida en general)if_return
(predeterminado:true
) -- optimizaciones para if/return y if/continueinline
(predeterminado:true
) -- llamadas en línea para funcionar conreturn
declaración simple/:false
--igual que0
0
- línea deshabilitada1
-- funciones simples en línea2
-- funciones en línea con argumentos3
-- funciones en línea con argumentos y variablestrue
--igual que3
join_vars
(predeterminado:true
) -- unirvar
declaraciones consecutivaskeep_fargs
(predeterminado:true
): evita que el compresor descarte argumentos de función no utilizados. Lo necesita para el código que se basa enFunction.length
.keep_fnames
(predeterminado:false
) - Pasatrue
para evitar que el compresor descarte nombres de funciones. Útil para el código que depende deFunction.prototype.name
. Consulte también: lakeep_fnames
opción mangle .keep_infinity
(predeterminado:false
): pasetrue
para evitarInfinity
que se comprima en1/0
, lo que puede causar problemas de rendimiento en Chrome.loops
( predeterminado:true
): optimizaciones parado
y bucles cuando podemos determinar estáticamente la condición.while
for
negate_iife
(predeterminado:true
): niega las "Expresiones de función llamadas inmediatamente" donde se descarta el valor de retorno, para evitar los pares que insertaría el generador de código.passes
(predeterminado:1
): el número máximo de veces que se ejecuta la compresión. En algunos casos, más de una pasada conduce a un código más comprimido. Tenga en cuenta que más pasadas llevarán más tiempo.properties
(predeterminado:true
): reescribe el acceso a la propiedad usando la notación de puntos, por ejemplofoo["bar"] → foo.bar
pure_funcs
(predeterminadonull
:) - Puede pasar una matriz de nombres y UglifyJS asumirá que esas funciones no producen efectos secundarios. PELIGRO: no verificará si el nombre se redefine en el alcance. Un caso de ejemplo aquí, por ejemplo.var q = Math.floor(a/b)
Si la variableq
es no se usa en ningún otro lugar, UglifyJS lo eliminará, pero seguirá manteniendo elMath.floor(a/b)
, sin saber lo que hace. Puede pasarpure_funcs: [ 'Math.floor' ]
para hacerle saber que esta función no producirá ningún efecto secundario, en cuyo caso se descartará toda la declaración. La implementación actual agrega algo de sobrecarga (la compresión será más lenta). Asegúrese de que los símbolos debajopure_funcs
también estén debajomangle.reserved
para evitar daños.pure_getters
(predeterminado:"strict"
) -- Si pasatrue
por esto, UglifyJS asumirá que el acceso a la propiedad del objeto (por ejemplo,foo.bar
ofoo["bar"]
) no tiene ningún efecto secundario. Especifique"strict"
tratarlofoo.bar
como libre de efectos secundarios solo cuandofoo
sea seguro que no se producirá, es decir, nonull
oundefined
.reduce_funcs
(predeterminado:true
): permite que las funciones de un solo uso se incluyan como expresiones de función cuando esté permitido, lo que permite una mayor optimización. Habilitado de forma predeterminada. La opción depende dereduce_vars
estar habilitada. Algunos códigos se ejecutan más rápido en el motor Chrome V8 si esta opción está deshabilitada. No impactar negativamente a otros navegadores importantes.reduce_vars
(predeterminadotrue
:): mejora la optimización de las variables asignadas y utilizadas como valores constantes.sequences
(predeterminado:true
): une declaraciones simples consecutivas usando el operador de coma. Puede configurarse en un entero positivo para especificar el número máximo de secuencias de coma consecutivas que se generarán. Si esta opción está configurada entrue
entonces el límite predeterminadosequences
es200
. Establecer opción afalse
o0
para deshabilitar. Lasequences
longitud más pequeña es2
. Unsequences
valor de1
está protegido para ser equivalente atrue
y como tal significa200
. En raras ocasiones, el límite de secuencias predeterminado conduce a tiempos de compresión muy lentos, en cuyo caso20
se recomienda un valor de o menos.side_effects
(predeterminado:true
): pasefalse
para deshabilitar funciones potencialmente eliminadas marcadas como "puras". Una llamada a función se marca como "pura" si hay una anotación de comentario/*@__PURE__*/
o/*#__PURE__*/
precede inmediatamente a la llamada. Por ejemplo:/*@__PURE__*/foo();
switches
(predeterminado:true
) -- eliminar duplicados y eliminarswitch
ramas inalcanzablestoplevel
(predeterminado:):false
elimine funciones sin referencia ("funcs"
) y/o variables ("vars"
) en el alcance del nivel superior (false
de forma predeterminada,true
para eliminar funciones y variables sin referencia)top_retain
(predeterminado:)null
: evita que se eliminen funciones y variables de nivel superior específicasunused
(pueden ser una matriz, separadas por comas, expresiones regulares o funciones. Implicatoplevel
) .typeofs
(predeterminado:true
) - Se transformatypeof foo == "undefined"
enfoo === void 0
Nota: se recomienda establecer este valorfalse
en IE10 y versiones anteriores debido a problemas conocidos.unsafe
(predeterminado:)false
: aplica transformaciones "inseguras" (discusión a continuación)unsafe_comps
(predeterminado:)false
: comprime expresiones comoa <= b
asumir que ninguno de los operandos puede ser (obligado a hacerlo)NaN
.unsafe_Function
(predeterminado:false
): comprime y destrozaFunction(args, code)
cuando ambosargs
ycode
son literales de cadena.unsafe_math
(predeterminado:false
): optimiza expresiones numéricas como2 * x * 3
into6 * x
, lo que puede dar resultados de punto flotante imprecisos.unsafe_proto
(predeterminadofalse
:) - optimiza expresiones comoArray.prototype.slice.call(a)
en[].slice.call(a)
unsafe_regexp
(predeterminadofalse
:): habilita la sustitución de variables conRegExp
valores de la misma manera que si fueran constantes.unsafe_undefined
(predeterminado:false
): sustituirvoid 0
si hay una variable nombradaundefined
en el alcance (el nombre de la variable se alterará, generalmente se reducirá a un solo carácter)unused
(predeterminado:true
): elimina funciones y variables sin referencia (las asignaciones de variables directas simples no cuentan como referencias a menos que se establezcan en"keep_assign"
)warnings
(predeterminadofalse
:): muestra advertencias cuando se elimina código inalcanzable o declaraciones no utilizadas, etc.
Opciones de destrucción
eval
(predeterminadofalse
): pasatrue
para modificar los nombres visibles en los ámbitos donde se utilizaneval
o .with
keep_fnames
(predeterminadofalse
) - Pasartrue
para no alterar los nombres de las funciones. Útil para el código que depende deFunction.prototype.name
. Consulte también: lakeep_fnames
opción de compresión .reserved
(predeterminado[]
): pasa una serie de identificadores que deben excluirse de la manipulación. Ejemplo:["foo", "bar"]
.toplevel
(predeterminadofalse
): pasatrue
para modificar los nombres declarados en el ámbito de nivel superior.
Ejemplos:
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
): se utilizatrue
para permitir la manipulación de las propiedades DOM integradas. No se recomienda anular esta configuración.debug
(predeterminado:false
) -- Destruye nombres con el nombre original aún presente. Pase una cadena vacía""
para habilitar, o una cadena no vacía para establecer el sufijo de depuración.keep_quoted
(predeterminadofalse
:): solo modifica los nombres de propiedades sin comillas.regex
(predeterminadonull
:): pase un literal RegExp para alterar solo los nombres de propiedades que coincidan con la expresión regular.reserved
(predeterminado:[]
): no altere los nombres de propiedades que figuran en lareserved
matriz.
Opciones de salida
El generador de código intenta generar el código más corto posible de forma predeterminada. En caso de que desee una salida embellecida, pase --beautify
( -b
). Opcionalmente, puede pasar argumentos adicionales que controlen la salida del código:
ascii_only
(predeterminadofalse
): caracteres Unicode de escape en cadenas y expresiones regulares (afecta a las directivas con caracteres no ASCII que dejan de ser válidos)beautify
(predeterminadotrue
): si realmente se debe embellecer la salida. Pasar-b
establecerá esto en verdadero, pero es posible que necesites pasar-b
incluso cuando quieras generar código minimizado, para especificar argumentos adicionales, para que puedas usarlos-b beautify=false
para anularlo.braces
(predeterminadofalse
): siempre inserte llaves en las declaracionesif
,, o , inclusofor
si su cuerpo es una sola declaración.do
while
with
comments
(predeterminadofalse
): pasatrue
o"all"
conserva todos los comentarios,"some"
para conservar algunos comentarios, una cadena de expresión regular (p. ej./^!/
) o una función.indent_level
(por defecto4
)indent_start
(predeterminado0
): prefije todas las líneas con esa cantidad de espaciosinline_script
(predeterminadotrue
): escapa de los comentarios HTML y la barra diagonal en las apariciones de</script>
cadenaskeep_quoted_props
(predeterminadofalse
): cuando está activado, evita eliminar las comillas de los nombres de propiedades en los literales de los objetos.max_line_len
(predeterminadofalse
): longitud máxima de línea (para código feo)preamble
(predeterminadonull
): cuando se pasa, debe ser una cadena y se antepondrá literalmente a la salida. El mapa fuente se ajustará a este texto. Puede usarse para insertar un comentario que contenga información de licencia, por ejemplo.preserve_line
(predeterminadofalse
): pasatrue
para conservar líneas, pero solo funciona sibeautify
está configurado enfalse
.quote_keys
(predeterminadofalse
): pasatrue
para citar todas las claves en objetos literalesquote_style
(predeterminado0
): estilo de comillas preferido para cadenas (también afecta a los nombres de propiedades y directivas entre comillas):0
-- prefiere comillas dobles, cambia a comillas simples cuando hay más comillas dobles en la cadena misma.0
Es mejor para el tamaño gzip.1
-- utilice siempre comillas simples2
-- utilice siempre comillas dobles3
-- utilice siempre las comillas originales
semicolons
(predeterminadotrue
): declaraciones separadas con punto y coma. Si lo aprueba,false
siempre que sea posible usaremos una nueva línea en lugar de un punto y coma, lo que generará una salida más legible del código feo (el tamaño antes de gzip podría ser más pequeño; el tamaño después de gzip ligeramente más grande).shebang
(predeterminadotrue
): conserva shebang#!
en el preámbulo (scripts de bash)webkit
(predeterminadofalse
): habilita soluciones para errores de WebKit. Los usuarios de PhantomJS deben configurar esta opción entrue
.width
(predeterminado80
): solo tiene efecto cuando el embellecimiento está activado, esto especifica un ancho de línea (orientativo) que el embellecedor intentará obedecer. Se refiere al ancho de la línea de texto (excluyendo la sangría). No funciona muy bien. actualmente, pero hace que el código generado por UglifyJS sea más legible.wrap_iife
(predeterminadofalse
): pasatrue
para ajustar las expresiones de función invocadas inmediatamente. Consulte el n.° 640 para obtener más detalles.
Misceláneas
Keeping copyright notices or other comments
Puede pasar --comments
para conservar ciertos comentarios en la salida. De forma predeterminada, mantendrá los comentarios de estilo JSDoc que contengan "@preserve", "@license" o "@cc_on" (compilación condicional para IE). Puede pasar
--comments all
para conservar todos los comentarios o una expresión regular de JavaScript válida para conservar solo los comentarios que coincidan con esta expresión regular. Por ejemplo, --comments /^!/
mantendrá comentarios como /*! Copyright Notice */
.
Sin embargo, tenga en cuenta que puede haber situaciones en las que los comentarios se pierdan. Por ejemplo:
1
2
3
4
5
6
7function f() {
/** @preserve Foo Bar */
function g() {
// this function is never called
}
return something();
}
Aunque tenga "@preserve", el comentario se perderá porque g
el compresor descarta la función interna (que es el nodo AST al que está adjunto el comentario) como no referenciada.
Los comentarios más seguros donde colocar información de derechos de autor (u otra información que deba mantenerse en la salida) son los comentarios adjuntos a los nodos de nivel superior.
La unsafe
compress
opción
Permite algunas transformaciones que podrían romper la lógica del código en ciertos casos artificiales, pero debería funcionar bien para la mayoría del código. Es posible que quieras probarlo en tu propio código, debería reducir el tamaño minimizado. Esto es lo que sucede cuando este indicador está activado:
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 (...)
→ descartamos elnew
Conditional compilation
Puede usar el modificador --define
( -d
) para declarar variables globales que UglifyJS asumirá como constantes (a menos que estén definidas en el alcance). Por ejemplo, si lo pasa --define DEBUG=false
, junto con la eliminación del código inactivo, UglifyJS descartará lo siguiente de la salida:
1
2
3if (DEBUG) {
console.log("debug stuff");
}
Puede especificar constantes anidadas en formato --define env.DEBUG=false
.
UglifyJS advertirá sobre la condición siempre falsa y sobre la eliminación de código inalcanzable; por ahora no hay ninguna opción para desactivar solo esta advertencia específica, puede pasar warnings=false
para desactivar todas las advertencias.
Otra forma de hacerlo es declarar sus globales como constantes en un archivo separado e incluirlo en la compilación. Por ejemplo, puede tener un
build/defines.js
archivo con lo siguiente:
1
2
3var DEBUG = false;
var PRODUCTION = true;
// etc.
y construye tu código así:
1uglifyjs build/defines.js js/foo.js js/bar.js... -c
UglifyJS notará las constantes y, dado que no se pueden modificar, evaluará las referencias a ellas con el valor mismo y eliminará el código inalcanzable como de costumbre. La compilación contendrá las const
declaraciones si las usa. Si se dirige a entornos <ES6, lo cual no no es compatible const
, usar var
with reduce_vars
(habilitado de forma predeterminada) debería ser suficiente.
Conditional compilation API
También puedes usar la compilación condicional a través de la API programática, con la diferencia de que el nombre de la propiedad es global_defs
y es una propiedad del 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 reemplazar un identificador con una expresión arbitraria no constante, es necesario anteponer la global_defs
clave con "@"
para indicarle a UglifyJS que analice el valor como una expresión:
1
2
3
4
5
6
7
8UglifyJS.minify("alert('hello');", {
compress: {
global_defs: {
"@alert": "console.log"
}
}
}).code;
// returns: 'console.log("hello");'
De lo contrario, sería reemplazado como cadena literal:
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
La transformación transversal y de la AST nativa se puede realizar mediante
TreeWalker
y
TreeTransformer
respectivamente.
ESTree / SpiderMonkey AST
UglifyJS tiene su propio formato de árbol de sintaxis abstracta; por razones prácticas, no podemos cambiar fácilmente al uso de SpiderMonkey AST internamente. Sin embargo, UglifyJS ahora tiene un convertidor que puede importar un SpiderMonkey AST.
Por ejemplo , Acorn es un analizador súper rápido que produce un AST SpiderMonkey. Tiene una pequeña utilidad CLI que analiza un archivo y vuelca el AST en JSON en la salida estándar. Para usar UglifyJS para manipularlo y comprimirlo:
1acorn file.js | uglifyjs -p spidermonkey -m -c
La -p spidermonkey
opción le dice a UglifyJS que todos los archivos de entrada no son JavaScript, sino código JS descrito en SpiderMonkey AST en JSON. Por lo tanto, no usamos nuestro propio analizador en este caso, sino que simplemente transformamos ese AST en nuestro AST interno.
Use Acorn for parsing
Más por diversión, agregué la -p acorn
opción que usará Acorn para hacer todo el análisis. Si pasas esta opción, UglifyJS lo hará require("acorn")
.
Acorn es realmente rápido (por ejemplo, 250 ms en lugar de 380 ms en un código de 650 K), pero convertir el árbol SpiderMonkey que produce Acorn requiere otros 150 ms, por lo que en total es un poco más que simplemente usar el propio analizador de UglifyJS.
Uglify Fast Minify Mode
No es muy conocido, pero la eliminación de espacios en blanco y la alteración de símbolos representan el 95% de la reducción de tamaño en el código minificado para la mayoría de JavaScript (no transformaciones de código elaboradas). Uno simplemente puede desactivarlo compress
para acelerar las compilaciones de Uglify de 3 a 4 veces mangle
. El único modo Uglify tiene velocidades de minificación y tamaños de gzip comparables a
butternut
:
d3.js | minimizar el tamaño | tamaño zip | minimizar el tiempo (segundos) |
---|---|---|---|
original | 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=verdadero, comprimir=falso | 220,216 | 72.730 | 1.13 |
nuez@0.4.6 | 217,568 | 72.738 | 1.41 |
uglify-js@3.0.24 mangle=verdadero, comprimir=verdadero | 212,511 | 71.560 | 3.36 |
babili@0.1.4 | 210,713 | 72.140 | 12.64 |
Para habilitar el modo de minificación rápida desde el uso CLI:
1uglifyjs file.js -m
Para habilitar el modo de minificación rápida con el uso de API:
1UglifyJS.minify(code, { compress: false, mangle: true });
Mapas fuente y depuración.
Se sabe que varias compress
transformaciones que simplifican, reorganizan, incorporan y eliminan código tienen un efecto adverso en la depuración con mapas fuente. Esto es de esperarse ya que el código se optimiza y las asignaciones a menudo simplemente no son posibles porque parte del código ya no existe. La depuración de mapas desactiva la opción Uglify compress
y simplemente usa mangle
.
Compiler assumptions
Para permitir mejores optimizaciones, el compilador hace varias suposiciones:
.toString()
y.valueOf()
no tienen efectos secundarios, y para los objetos integrados no se han anulado.undefined
yNaN
noInfinity
han sido redefinidos externamente.arguments.callee
y no se utilizanarguments.caller
.Function.prototype.caller
- El código no espera que el contenido
Function.prototype.toString()
seaError.prototype.stack
nada en particular. - Obtener y configurar propiedades en un objeto simple no causa otros efectos secundarios (usando
.watch()
oProxy
). - Las
propiedades del objeto se pueden agregar, eliminar y modificar (no se impide con
Object.defineProperty()
,Object.defineProperties()
, o ).Object.freeze()
Object.preventExtensions()
Object.seal()