UglifyJS 3
UglifyJS es un kit 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 conuglify-js@2
. - La documentación para las versiones de UglifyJS
2.x
se puede encontrar aquí . -
uglify-js
solo es compatible con JavaScript (ECMAScript 5). - To minify ECMAScript 2015 or above , transpile utilizando 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 una 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 múltiples archivos de entrada. Se recomienda que primero pase los archivos de entrada, luego pase 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 se combinará 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, sepárelos con un doble guión para evitar que los archivos 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 el archivo de salida. De lo contrario, la salida irá a STDOUT.
Opciones de mapa fuente de CLI
UglifyJS puede generar un archivo de mapa fuente, que 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 fuente.--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 que se está utilizando HTTPX-SourceMap
y omitirá la directiva//# sourceMappingURL=
.
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 file1.js
y file2.js
, file2.js
la salida en foo.min.js
y el mapa fuente en foo.min.js.map
. El mapa fuente se referirá a http://foo.com/src/js/file1.js
y http://foo.com/src/js/file2.js
(de hecho, incluirá http://foo.com/src
como la raíz del mapa fuente y los archivos originales como js/file1.js
y js/file2.js
).
Composed source map
Cuando está comprimiendo el código JS que fue generado por un compilador como CoffeeScript, la asignación al código JS no será demasiado útil. En cambio, le gustaría volver al mapa original (es decir, CoffeeScript). UglifyJS tiene un opción para tomar un mapa fuente de entrada Suponiendo que tiene un mapeo de CoffeeScript → JS compilado, UglifyJS puede generar un mapa de CoffeeScript → JS comprimido mapeando cada token en el JS compilado a su ubicación original.
Para usar 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
--compress
pasar --compress
( -c
) para habilitar el compresor. Opcionalmente, puede pasar una lista de opciones de compresión separadas por comas.
Las opciones están en la forma foo=bar
, o simplemente foo
(esta última implica una opción booleana que desea establecer como true
; es efectivamente un atajo para foo=true
).
Ejemplo:
1uglifyjs file.js -c toplevel,sequences=false
Opciones de cambio de CLI
Para habilitar el administrador necesita pasar --mangle
( -m
). Se --mangle
siguientes opciones (separadas por comas):
toplevel
(por defectofalse
) -mangle nombres declarados en el ámbito de nivel superior.eval
(por defectofalse
) - mangle nombres visibles en el DONDE Scopeseval
owith
se utilizan.
Cuando se habilita la anulación pero desea evitar que ciertos nombres se anulen, 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 require
cambios, exports
y $
nombres.
Nombres de propiedades de --mangle-props
CLI ( --mangle-props
)
Nota: ESTO PROBABLEMENTE ROMPIRÁ SU CÓDIGO. La manipulación de nombres de propiedades es un paso separado, diferente de la --mangle-props
nombres de variables. Pase --mangle-props
para habilitarlo. Destrozará todas las propiedades en el código de entrada con la excepción de las propiedades DOM incorporadas y propiedades en las clases principales de JavaScript. 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());
Mangle 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());
Mangle todas las propiedades excepto las propiedades reserved
:
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._());
Descomprima todas las propiedades que coincidan con una 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 estándar de JS por defecto ( --mangle-props builtins
para anular).
Se proporciona un archivo de exclusión predeterminado en tools/domprops.json
que debe cubrir la mayoría de las propiedades estándar de JS y DOM definidas en varios navegadores. Pase --mangle-props domprops
para deshabilitar esta característica.
Se puede usar una expresión regular para definir qué nombres de propiedad se deben --mangle-props regex=/^_/
, por ejemplo, --mangle-props regex=/^_/
solo alterará los nombres de propiedades que comienzan con un guión bajo.
Cuando comprime varios archivos con esta opción, para que funcionen juntos al final, debemos asegurarnos de alguna manera de que una propiedad se destruya con el mismo nombre en todos ellos. Para esto, pase --name-cache filename.json
y UglifyJS mantendrá estas asignaciones en un archivo que luego se puede reutilizar. Debería estar inicialmente 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 propiedad destrozados.
No es necesario usar el nombre de caché si comprime todos sus archivos en una sola llamada a UglifyJS.
--mangle-props keep_quoted
nombres sin comillas ( --mangle-props keep_quoted
)
El uso del nombre de la propiedad entre comillas ( o["foo"]
) reserva el nombre de la propiedad ( foo
) para que no se altere en todo el script, incluso cuando se utiliza en un estilo sin comillas ( o.foo
). Ejemplo:
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
cambiaría a o._$foo$_
con esta opción. Esto permite la manipulación de propiedades de una base de código grande sin dejar de ser capaz de depurar el código e identificar dónde destrozar está rompiendo 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 o.foo
a o._$foo$XYZ_
. Puede cambiar esto cada vez que compila un script para identificar cómo una propiedad se destrozó Una técnica consiste en pasar un número aleatorio en cada compilación para simular cambios de manipulació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 maltratadas en el almacenamiento.
Referencia de API
Asumiendo la instalación a través de NPM, puede cargar UglifyJS en su aplicación de esta manera:
1var UglifyJS = require("uglify-js");
Hay una sola función de alto nivel, minify(code, options)
, que realizará todas las fases de minificación de manera 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 minify
más de un archivo JavaScript a la vez utilizando 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 opción de nivel toplevel
:
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 opción nameCache
:
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 nombre de caché 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 opciones minify()
:
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 , the
API 3.x` 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;
Opciones de minificar
warnings
(valor predeterminadofalse
): pasetrue
para devolver las advertencias del compresor enresult.warnings
. Utilice el valor"verbose"
para obtener advertencias más detalladas.parse
(predeterminado{}
): pasa un objeto si desea especificar algunas opciones de análisis adicionales .compress
(predeterminado{}
): pasafalse
para omitir la compresión por completo. Pasa un objeto para especificar opciones de compresión personalizadas.mangle
(valor predeterminadotrue
): pasarfalse
para omitir nombres de cambio, o pasar un objeto para especificar opciones de cambio (ver más abajo).-
mangle.properties
(valor predeterminadofalse
): una subcategoría de la opción mangle. Pase un objeto para especificar opciones de propiedades de mangle personalizadas.
-
output
(null
predeterminado): pase un objeto si desea especificar opciones de salida adicionales . Los valores predeterminados están optimizados para una mejor compresión.sourceMap
(false
predeterminado): pase un objeto si desea especificar las opciones del mapa fuente .toplevel
(valor predeterminadofalse
)toplevel
atrue
si desea habilitar la variable de nivel superior y el cambio de nombre de función y descartar variables y funciones no utilizadas.nameCache
(null
predeterminado):nameCache
un objeto vacío{}
o un objetonameCache
utilizadonameCache
si desea almacenar en caché los nombres de variables y propiedades en varias invocaciones deminify()
. Nota: esta es una propiedad de lectura / escritura.minify()
will lea el estado de la memoria caché de nombre de este objeto y actualícelo durante la minificación para que el usuario pueda reutilizarlo o conservarlo de forma externa.ie8
(valor predeterminadofalse
) -conjunto atrue
para admitir IE8.keep_fnames
(predeterminado:false
) -passtrue
para evitar descartar o alterar los nombres de las funciones. Útil para el código que se basa enFunction.prototype.name
.
Estructura de opciones de minify
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 fuente no se guarda en un archivo, solo se devuelve en result.map
. El valor pasado para sourceMap.url
solo se usa para establecer //# sourceMappingURL=out.js.map
en result.code
. El valor de filename
solo se utiliza para establecer file
atributo de file
(ver las especificaciones ) en el archivo de mapa fuente.
Puede configurar la opción sourceMap.url
para que esté "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, 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 está utilizando el encabezado X-SourceMap
, puede omitir sourceMap.url
.
Opciones de análisis
bare_returns
(valor predeterminadofalse
):bare_returns
declaraciones dereturn
nivel superiorhtml5_comments
(valor predeterminadotrue
)#!command
shebang
(predeterminadotrue
) -support#!command
como primera línea
Opciones de compresión
arguments
(predeterminado:true
): reemplaza losarguments[index]
con el nombre del parámetro de función siempre que sea posible.booleans
(valor predeterminado:true
):booleans
optimizaciones para el contexto booleano, por ejemplo!!a ? b : c → a ? b : c
collapse_vars
(valor predeterminado:true
) -Contraer variables no constantes de un solo uso, si los efectos secundarios lo permiten.comparisons
(valor predeterminado:true
): aplique ciertas optimizaciones a los nodos binarios, por ejemplo!(a <= b) → a > b
, intenta negar los nodos binarios, por ejemploa = !b && !c && !d && !e → a=!(b||c||d||e)
etc.conditionals
(predeterminado:true
) optimizaciones de aplicación paraif
-s y expresiones condicionalesdead_code
(predeterminado:true
)dead_code
código inalcanzabledrop_console
(valor predeterminado:false
) -Passtrue
para descartar llamadas a laconsole.*
funciones. Si desea descartar una llamada de función específica comoconsole.info
y / o retener los efectos secundarios de los argumentos de la función después depure_funcs
llamada a la función, utilicepure_funcs
en su lugardrop_debugger
(predeterminado:true
)drop_debugger
debugger;
declaracionesevaluate
(predeterminado:true
) -intento para evaluar expresiones constantesexpression
(predeterminado:false
) -Passtrue
para preservar los valores de finalización de las declaraciones de terminal sinreturn
, por ejemplo, en marcadores.global_defs
(predeterminado:{}
) -ver compilación condicionalhoist_funs
(predeterminado:false
)hoist_funs
declaraciones de funcioneshoist_props
(predeterminado:true
)hoist_props
propiedades dehoist_props
de objetos constantes y literales de matriz en variables regulares sujetas a un conjunto de restricciones.Por ejemplo:var o={p:1, q:2}; f(op, oq);
es convertido af(1, 2);
Nota:hoist_props
funciona mejor con la función demangle
habilitada, la opción decompress
passes
establecida a2
o superior, y la opción decompress
toplevel
habilitado.hoist_vars
(predeterminado:false
)hoist_vars
declaraciones devar
(esto esfalse
de forma predeterminada porque parece aumentar el tamaño de la salida en general)if_return
(predeterminado:true
)if_return
para if / return y if / continueinline
(predeterminado:true
) -inline llama a funcionar con una declaración simple /return
:-
false
mismo como0
-
0
desactivada -
1
funciones simples en línea -
2
funciones en línea con argumentos -
3
funciones en línea con argumentos y variables -
true
mismo que3
-
join_vars
(predeterminado:true
)join_vars
declaracionesvar
consecutivaskeep_fargs
(valor predeterminado:true
): evita que el compresor descarte los argumentos de función no utilizados. Lo necesita para el código que se basa enFunction.length
.keep_fnames
(valor predeterminado:false
)keep_fnames
true
para evitar que el compresor descarte los nombres de funciones. Útil para el código que se basa enFunction.prototype.name
. Consulte también: la opción dekeep_fnames
.keep_infinity
(predeterminado:false
):keep_infinity
true
para evitar queInfinity
se comprima en1/0
, lo que puede causar problemas de rendimiento en Chrome.loops
(predeterminado:true
): optimizaciones parado
,while
yfor
bucles cuando podemos determinar estáticamente la condición.negate_iife
(predeterminado:true
)negate_iife
"Expresiones de funcionesnegate_iife
inmediato" donde se descarta el valor de retorno, para evitar los elementos parentales 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 un pase conduce a un código comprimido adicional. Tenga en cuenta que más pases tomarán más tiempo.properties
(valor predeterminado:true
): escriba el acceso a la propiedad utilizando la notación de punto, por ejemplofoo["bar"] → foo.bar
pure_funcs
(predeterminado:null
): puede pasar una matriz de nombres y UglifyJS asumirá que esas funciones no producen efectos secundarios. PELIGRO: no comprobará si el nombre se redefine en el alcance. Un caso de ejemplo aquí, por ejemplovar q = Math.floor(a/b)
. Si la variableq
no se usa en otro lugar, UglifyJS la soltará, pero seguirá manteniendoMath.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 la declaración completa se descartaría. La implementación actual agrega algo de sobrecarga (la compresión será más lenta). Asegúrese de que los símbolos bajopure_funcs
también bajomangle.reserved
para evitar destrozos.pure_getters
(predeterminado:"strict"
) -Si pasatrue
para 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"
para tratefoo.bar
como libre de efectos secundarios solo cuando es seguro quefoo
no lanzará, es decir, no seránull
oundefined
.reduce_funcs
(predeterminado:true
)reduce_funcs
las funciones de un solo uso se inserten como expresiones de función cuando sea permisible, lo que permite una mayor optimización. Habilitada de manera predeterminada. La opción depende de que sereduce_vars
. Algunos códigos se ejecutan más rápido en el motor Chrome V8 si esta opción está deshabilitada No afecta negativamente a otros navegadores importantes.reduce_vars
(predeterminado:true
)reduce_vars
optimización en variables asignadas y utilizadas como valores constantes.sequences
(predeterminado:true
): se unen a sentencias simples consecutivas utilizando el operador de coma. Se puede establecer en un entero positivo para especificar el número máximo de secuencias de coma consecutivas que se generarán. Si esta opción se establece entrue
, el límite desequences
predeterminado es200
Establezca la opción enfalse
o0
para deshabilitarla. La longitud más pequeña de lassequences
es2
Un valor desequences
de1
es equivalente atrue
y, como tal, significa200
En raras ocasiones, el límite predeterminado de secuencias conduce a tiempos de compresión muy lentos. en cuyo caso se recomienda un valor de20
o menos.side_effects
(predeterminado:true
)side_effects
false
para deshabilitar las funciones potencialmenteside_effects
marcadas como "puro". Una llamada de función se marca como "puro" si una anotación de comentario/*@__PURE__*/
o/*#__PURE__*/
inmediatamente precede a llamada. Por ejemplo:/*@__PURE__*/foo();
switches
(predeterminado:true
) -de-duplicate y elimina ramas deswitch
inalcanzablestoplevel
(predeterminado:false
)"funcs"
funciones sin referencia ("funcs"
) y / o variables ("vars"
) en el ámbito de nivel superior (false
por defecto,true
para descartar tanto las funciones como las variables sin referencia)top_retain
(predeterminado:null
):top_retain
funciones y variables específicas de niveltop_retain
de la eliminaciónunused
(puede ser matriz, separados por comas, RegExp o función. Implica niveltoplevel
)typeofs
(predeterminado:true
)typeofs
typeof foo == "undefined"
enfoo === void 0
Nota: se recomienda establecer este valor enfalse
para IE10 y versiones anteriores debido a problemas conocidos.unsafe
(predeterminado:false
) -aplicar transformaciones "inseguras" (discusión a continuación)unsafe_comps
(valor predeterminado:false
)unsafe_comps
expresiones comoa <= b
suponiendo que ninguno de los operandos pueda ser (forzado a)NaN
.unsafe_Function
(predeterminado:false
)unsafe_Function
y mangleFunction(args, code)
cuando tantoargs
comocode
son literales de cadena.unsafe_math
(predeterminado:false
):unsafe_math
expresiones numéricas como2 * x * 3
en6 * x
, lo que puede dar resultados imprecisos de coma flotante.unsafe_proto
(predeterminado:false
):unsafe_proto
expresiones comoArray.prototype.slice.call(a)
en[].slice.call(a)
unsafe_regexp
(predeterminado:false
)unsafe_regexp
sustituciones de variables con valoresRegExp
la misma manera que si fueran constantes.unsafe_undefined
(por defecto:false
) -sustituyevoid 0
si hay una variable llamadaundefined
en alcance (el nombre de la variable será mutilado, generalmente reducido a un solo carácter)unused
(por defecto:true
) - Funciones caen sin referencias y las variables (las simples asignaciones de variables directos no cuentan como el menos que el SET a las referencias"keep_assign"
)warnings
(predeterminado:false
): muestra advertencias al soltar código inalcanzable o declaraciones no utilizadas, etc.
Opciones de mangle
eval
(valor predeterminadofalse
) -Passtrue
para alterar nombres visibles en ámbitos donde se utilizaneval
owith
.keep_fnames
(valor predeterminadofalse
)keep_fnames
true
para nokeep_fnames
nombres de funciones. Útil para el código que se basa enFunction.prototype.name
. Consulte también: la opción de compresiónkeep_fnames
.reserved
(predeterminado[]
) -Pasar una matriz de identificadores que deben excluirse de la manipulación. Ejemplo:["foo", "bar"]
.toplevel
(por defectofalse
) -Passtrue
para destrozar 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
(valor predeterminado:false
): se usatrue
para permitir la manipulación de propiedades DOM integradas. No se recomienda anular esta configuración.debug
(predeterminado:false
) -— Mangle los nombres con el nombre original todavía presente. Pase una cadena vacía""
para habilitarla, o una cadena no vacía para establecer el sufijo de depuración.keep_quoted
(valor predeterminado:false
) -— Solo destrozar nombres de propiedades sin comillas.regex
(valor predeterminado:null
): pase un literal RegExp para alterar solo los nombres de propiedades que coincidan con la expresión regular.reserved
(predeterminado:[]
) -No alterar los nombres de propiedades que figuran en la matrizreserved
.
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
)ascii_only
caracteres Unicode en cadenas y expresiones regulares (afecta a las directivas con caracteres no ascii que no son válidos)beautify
(true
defecto) -si realmente embellecer la salida. Pasar-b
establecerá esto en verdadero, pero es posible que deba pasar-b
incluso cuando desee generar código minificado, para especificar argumentos adicionales, para que pueda use-b beautify=false
para anularlo.braces
(por defectofalse
): siempre inserta llaves enif
,for
,do
,while
owith
declaraciones, incluso si su cuerpo es una sola declaración.comments
(valor predeterminadofalse
) -passtrue
o"all"
para preservar todos los comentarios,"some"
para preservar algunos comentarios, una cadena de expresión regular (por ejemplo,/^!/
) o una función.indent_level
(predeterminado4
)indent_start
(predeterminado0
) -prefijar todas las líneas por tantos espaciosinline_script
(true
predeterminado)inline_script
comentarios HTML y la barra diagonal en las apariciones de</script>
en cadenaskeep_quoted_props
(valor predeterminadofalse
):keep_quoted_props
activa, evita que se eliminen las comillas de los nombres de propiedad en literales de objeto.max_line_len
(false
predeterminado)max_line_len
línea (para código uglified)preamble
(null
predeterminado): cuando se pasa, debe ser una cadena y se agregará literalmente a la salida literalmente. El mapa fuente se ajustará para este texto. Se puede utilizar para insertar un comentario que contenga información de licencia, por ejemplo.preserve_line
(por defectofalse
) -passtrue
para preservar líneas, pero solo funciona sibeautify
se establece enfalse
.quote_keys
(valor predeterminadofalse
)quote_keys
true
para citar todas las claves en objetos literalesestilo de cotización preferido para las cadenas de caracteres
quote_style
(valor predeterminado0
) (afecta también a los nombres de propiedad y directivas entrecomillados):-
0
-prefiere comillas dobles, cambia a comillas simples cuando hay más comillas dobles en la cadena en sí.0
es mejor para el tamaño de gzip. -
1
-siempre use comillas simples -
2
-siempre use comillas dobles -
3
-siempre use las citas originales
-
semicolons
ysemicolons
(predeterminadotrue
): separe las declaraciones con punto y coma. Si pasafalse
, siempre que sea posible usaremos una nueva línea en lugar de un punto y coma, lo que dará como resultado una salida más legible de código uglified (el tamaño antes de gzip podría ser menor; el tamaño después de gzip es insignificantemente más grande) )shebang
(true
predeterminado) -conserva shebang#!
en preámbulo (scripts bash)webkit
(por defectofalse
) habilita soluciones para los errores de WebKit. Los usuarios de PhantomJS deben establecer 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 del texto de la línea (excluyendo la sangría). No funciona muy bien actualmente, pero hace que el código generado por UglifyJS sea más legible.wrap_iife
(valor predeterminadofalse
)wrap_iife
true
para ajustar las expresiones de función invocadas de inmediato. Consulte # 640 para obtener más detalles.
Misceláneo
Keeping copyright notices or other comments
Usted puede pasar por --comments
La conservar algunos de Comentarios La salida de forma predeterminada en TI-estilo le mantendrá jsdoc que contienen comentarios "@preserve", "@license" o "@cc_on" (compilación condicional para los IEs) Pasar por Puede.. --comments all
to keep all the comments, or a valid JavaScript regexp to keep only comments that match this regexp. For example --comments /^!/
will keep comments like /*! Copyright Notice */
.
Note, however, that there might be situations where comments are lost. For example:
1
2
3
4
5
6
7function f() {
/** @preserve Foo Bar */
function g() {
// this function is never called
}
return something();
}
Even though it has "@preserve", the comment will be lost because the inner function g
(which is the AST node to which the comment is attached to) is discarded by the compressor as not referenced.
The safest comments where to place copyright information (or other info that needs to be kept in the output) are comments attached to toplevel nodes.
The unsafe
compress
option
It enables some transformations that might break code logic in certain contrived cases, but should be fine for most code. You might want to try it on your own code, it should reduce the minified size. Here's what happens when this flag is on:
-
new Array(1, 2, 3)
orArray(1, 2, 3)
→[ 1, 2, 3 ]
-
new Object()
→{}
-
String(exp)
orexp.toString()
→"" + exp
-
new Object/RegExp/Function/Error/Array (...)
→ we discard thenew
Conditional compilation
You can use the --define
( -d
) switch in order to declare global variables that UglifyJS will assume to be constants (unless defined in scope). For example if you pass --define DEBUG=false
then, coupled with dead code removal UglifyJS will discard the following from the output:
1
2
3if (DEBUG) {
console.log("debug stuff");
}
You can specify nested constants in the form of --define env.DEBUG=false
.
UglifyJS will warn about the condition being always false and about dropping unreachable code; for now there is no option to turn off only this specific warning, you can pass warnings=false
to turn off all warnings.
Another way of doing that is to declare your globals as constants in a separate file and include it into the build. For example you can have a build/defines.js
file with the following:
1
2
3var DEBUG = false;
var PRODUCTION = true;
// etc.
and build your code like this:
1uglifyjs build/defines.js js/foo.js js/bar.js... -c
UglifyJS will notice the constants and, since they cannot be altered, it will evaluate references to them to the value itself and drop unreachable code as usual. The build will contain the const
declarations if you use them. If you are targeting < ES6 environments which does not support const
, using var
with reduce_vars
(enabled by default) should suffice.
Conditional compilation API
You can also use conditional compilation via the programmatic API. With the difference that the property name is global_defs
and is a compressor property:
1
2
3
4
5
6
7
8var result = UglifyJS.minify(fs.readFileSync("input.js", "utf8"), {
compress: {
dead_code: true,
global_defs: {
DEBUG: false
}
}
});
To replace an identifier with an arbitrary non-constant expression it is necessary to prefix the global_defs
key with "@"
to instruct UglifyJS to parse the value as an expression:
1
2
3
4
5
6
7
8UglifyJS.minify("alert('hello');", {
compress: {
global_defs: {
"@alert": "console.log"
}
}
}).code;
// returns: 'console.log("hello");'
Otherwise it would be replaced as string literal:
1
2
3
4
5
6
7
8UglifyJS.minify("alert('hello');", {
compress: {
global_defs: {
"alert": "console.log"
}
}
}).code;
// returns: '"console.log"("hello");'
Using native Uglify AST with minify()
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
Transversal and transformation of the native AST can be performed through TreeWalker
and TreeTransformer
respectively.
ESTree / SpiderMonkey AST
UglifyJS has its own abstract syntax tree format; for practical reasons we can't easily change to using the SpiderMonkey AST internally. However, UglifyJS now has a converter which can import a SpiderMonkey AST.
For example Acorn is a super-fast parser that produces a SpiderMonkey AST. It has a small CLI utility that parses one file and dumps the AST in JSON on the standard output. To use UglifyJS to mangle and compress that:
1acorn file.js | uglifyjs -p spidermonkey -m -c
The -p spidermonkey
option tells UglifyJS that all input files are not JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we don't use our own parser in this case, but just transform that AST into our internal AST.
Use Acorn for parsing
More for fun, I added the -p acorn
option which will use Acorn to do all the parsing. If you pass this option, UglifyJS will require("acorn")
.
Acorn is really fast (eg 250ms instead of 380ms on some 650K code), but converting the SpiderMonkey tree that Acorn produces takes another 150ms so in total it's a bit more than just using UglifyJS's own parser.
Uglify Fast Minify Mode
It's not well known, but whitespace removal and symbol mangling accounts for 95% of the size reduction in minified code for most JavaScript - not elaborate code transforms. One can simply disable compress
to speed up Uglify builds by 3 to 4 times. In this fast mangle
-only mode Uglify has comparable minify speeds and gzip sizes to butternut
:
d3.js | minify size | gzip size | minify time (seconds) |
---|---|---|---|
original | 451,131 | 108,733 | - |
uglify-js@3.0.24 mangle=false, compress=false | 316,600 | 85,245 | 0.70 |
uglify-js@3.0.24 mangle=true, compress=false | 220,216 | 72,730 | 1.13 |
butternut@0.4.6 | 217,568 | 72,738 | 1.41 |
uglify-js@3.0.24 mangle=true, compress=true | 212,511 | 71,560 | 3.36 |
babili@0.1.4 | 210,713 | 72,140 | 12.64 |
To enable fast minify mode from the CLI use:
1uglifyjs file.js -m
To enable fast minify mode with the API use:
1UglifyJS.minify(code, { compress: false, mangle: true });
Source maps and debugging
Various compress
transforms that simplify, rearrange, inline and remove code are known to have an adverse effect on debugging with source maps. This is expected as code is optimized and mappings are often simply not possible as some code no longer exists. For highest fidelity in source map debugging disable the Uglify compress
option and just use mangle
.
Compiler assumptions
To allow for better optimizations, the compiler makes various assumptions:
-
.toString()
and.valueOf()
don't have side effects, and for built-in objects they have not been overridden. -
undefined
,NaN
andInfinity
have not been externally redefined. -
arguments.callee
,arguments.caller
andFunction.prototype.caller
are not used. - The code doesn't expect the contents of
Function.prototype.toString()
orError.prototype.stack
to be anything in particular. - Getting and setting properties on a plain object does not cause other side effects (using
.watch()
orProxy
). - Object properties can be added , removed and modified (not prevented with
Object.defineProperty()
,Object.defineProperties()
,Object.freeze()
,Object.preventExtensions()
orObject.seal()
).