Impresionante módulo comunitario

UglifyJS 3

UglifyJS es un conjunto de herramientas de analizador, minificador, compresor y embellecedor de JavaScript.

Nota:

  • uglify-js@3tiene una API y una CLI simplificadas que no son compatibles con versiones anteriores deuglify-js@2 .
  • La documentación para 2.xlas versiones de UglifyJS se puede encontrar aquí .
  • uglify-jssolo 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:

1
npm install uglify-js -g

De NPM para uso programático:

1
npm install uglify-js

Uso de la línea de comando

1
uglifyjs [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:

1
uglifyjs --compress --mangle -- input.js

Command line options

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
-h, --help Print usage information. `--help options` for details on available options. -V, --version Print version number. -p, --parse <options> Specify parser options: `acorn` Use Acorn for parsing. `bare_returns` Allow return outside of functions. Useful when minifying CommonJS modules and Userscripts that may be anonymous function wrapped (IIFE) by the .user.js engine `caller`. `expression` Parse a single expression, rather than a program (for parsing JSON). `spidermonkey` Assume input files are SpiderMonkey AST format (as JSON). -c, --compress [options] Enable compressor/specify compressor options: `pure_funcs` List of functions that can be safely removed when their return values are not used. -m, --mangle [options] Mangle names/specify mangler options: `reserved` List of names that should not be mangled. --mangle-props [options] Mangle properties/specify mangler options: `builtins` Mangle property names that overlaps with standard JavaScript globals. `debug` Add debug prefix and suffix. `domprops` Mangle property names that overlaps with DOM properties. `keep_quoted` Only mangle unquoted properties. `regex` Only mangle matched property names. `reserved` List of names that should not be mangled. -b, --beautify [options] Beautify output/specify output options: `beautify` Enabled with `--beautify` by default. `preamble` Preamble to prepend to the output. You can use this to insert a comment, for example for licensing information. This will not be parsed, but the source map will adjust for its presence. `quote_style` Quote style: 0 - auto 1 - single 2 - double 3 - original `wrap_iife` Wrap IIFEs in parenthesis. Note: you may want to disable `negate_iife` under compressor options. -o, --output <file> Output file path (default STDOUT). Specify `ast` or `spidermonkey` to write UglifyJS or SpiderMonkey AST as JSON to STDOUT respectively. --comments [filter] Preserve copyright comments in the output. By default this works like Google Closure, keeping JSDoc-style comments that contain "@license" or "@preserve". You can optionally pass one of the following arguments to this flag: - "all" to keep all comments - a valid JS RegExp like `/foo/` or `/^!/` to keep only matching comments. Note that currently not *all* comments can be kept when compression is on, because of dead code removal or cascading statements into sequences. --config-file <file> Read `minify()` options from JSON file. -d, --define <expr>[=value] Global definitions. --ie8 Support non-standard Internet Explorer 8. Equivalent to setting `ie8: true` in `minify()` for `compress`, `mangle` and `output` options. By default UglifyJS will not try to be IE-proof. --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name. --name-cache <file> File to hold mangled name mappings. --self Build UglifyJS as a library (implies --wrap UglifyJS) --source-map [options] Enable source map/specify source map options: `base` Path to compute relative paths from input files. `content` Input source map, useful if you're compressing JS that was generated from some other original code. Specify "inline" if the source map is included within the sources. `filename` Name and/or location of the output source. `includeSources` Pass this flag if you want to include the content of source files in the source map as sourcesContent property. `root` Path to the original source to be included in the source map. `url` If specified, path to the source map to append in `//# sourceMappingURL`. --timings Display operations run time on STDERR. --toplevel Compress and/or mangle variables in top level scope. --verbose Print diagnostic messages. --warn Print warning messages. --wrap <name> Embed everything in a big function, making the “exports” and “global” variables available. You need to pass an argument to this option to specify the name that your module will take when included in, say, a browser.

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 que X-SourceMapse está utilizando HTTP y omitirá la //# sourceMappingURL=directiva.

Por ejemplo:

1 2 3
uglifyjs js/file1.js js/file2.js \ -o foo.min.js -c -m \ --source-map "root='http://foo.com/src',url='foo.min.js.map'"

Lo anterior comprimirá y destrozará file1.jsy file2.jscolocará la salida en foo.min.jsy el mapa de origen en foo.min.js.map. El mapeo de origen hará referencia a http://foo.com/src/js/file1.jsy 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.jsy 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:

1
uglifyjs 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(predeterminado false): modifica los nombres declarados en el ámbito de nivel superior.

  • eval(predeterminado false): modifica los nombres visibles en los ámbitos donde se utilizan evalo .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:

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

para evitar que se cambien los requirenombres 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-propspara 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
1
var 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 reservedpropiedades:

1
$ uglifyjs example.js -c -m --mangle-props reserved=[foo_,bar_]
1
var x={o:0,foo_:1,_:function(){return this.foo_+this.o}};x.bar_=2,x.o=3,console.log(x._());

Destroza todas las propiedades que coincidan con regex:

1
$ uglifyjs example.js -c -m --mangle-props regex=/_$/
1
var x={o:0,_:1,calc:function(){return this._+this.o}};x.l=2,x.o=3,console.log(x.calc());

Combinando opciones de propiedades de mangle:

1
$ uglifyjs example.js -c -m --mangle-props regex=/_$/,reserved=[bar_]
1
var x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log(x.calc());

Para que esto sea de alguna utilidad, evitamos alterar los nombres JS estándar de forma predeterminada ( --mangle-props builtinspara anular).

Se proporciona un archivo de exclusión predeterminado tools/domprops.jsonque debería cubrir la mayoría de las propiedades JS y DOM estándar definidas en varios navegadores. Pase --mangle-props dompropspara 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.jsy part2.jsserá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
1
var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);

Debugging property name mangling

También puede pasar --mangle-props debugpara 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
1
var 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.fooa 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:

1
var 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 4
var code = "function add(first, second) { return first + second; }"; var result = UglifyJS.minify(code); console.log(result.error); // runtime error, or `undefined` if no error console.log(result.code); // minified output: function add(n,d){return n+d}

Puede tener minifymá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 7
var code = { "file1.js": "function add(first, second) { return first + second; }", "file2.js": "console.log(add(1 + 2, 3 + 4));" }; var result = UglifyJS.minify(code); console.log(result.code); // function add(d,n){return d+n}console.log(add(3,7));

La toplevelopción:

1 2 3 4 5 6 7 8
var code = { "file1.js": "function add(first, second) { return first + second; }", "file2.js": "console.log(add(1 + 2, 3 + 4));" }; var options = { toplevel: true }; var result = UglifyJS.minify(code, options); console.log(result.code); // console.log(3+7);

La nameCacheopción:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var options = { mangle: { toplevel: true, }, nameCache: {} }; var result1 = UglifyJS.minify({ "file1.js": "function add(first, second) { return first + second; }" }, options); var result2 = UglifyJS.minify({ "file2.js": "console.log(add(1 + 2, 3 + 4));" }, options); console.log(result1.code); // function n(n,r){return n+r} console.log(result2.code); // console.log(n(3,7));

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 16
var cacheFileName = "/tmp/cache.json"; var options = { mangle: { properties: true, }, nameCache: JSON.parse(fs.readFileSync(cacheFileName, "utf8")) }; fs.writeFileSync("part1.js", UglifyJS.minify({ "file1.js": fs.readFileSync("file1.js", "utf8"), "file2.js": fs.readFileSync("file2.js", "utf8") }, options).code, "utf8"); fs.writeFileSync("part2.js", UglifyJS.minify({ "file3.js": fs.readFileSync("file3.js", "utf8"), "file4.js": fs.readFileSync("file4.js", "utf8") }, options).code, "utf8"); fs.writeFileSync(cacheFileName, JSON.stringify(options.nameCache), "utf8");

Un 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 21
var code = { "file1.js": "function add(first, second) { return first + second; }", "file2.js": "console.log(add(1 + 2, 3 + 4));" }; var options = { toplevel: true, compress: { global_defs: { "@console.log": "alert" }, passes: 2 }, output: { beautify: false, preamble: "/* uglified */" } }; var result = UglifyJS.minify(code, options); console.log(result.code); // /* uglified */ // alert(10);"

Para producir advertencias:

1 2 3 4 5 6
var code = "function f(){ var u; return 2 + 3; }"; var options = { warnings: true }; var result = UglifyJS.minify(code, options); console.log(result.error); // runtime error, `undefined` in this case console.log(result.warnings); // [ 'Dropping unused variable u [0:1,18]' ] console.log(result.code); // function f(){return 5}

Un ejemplo de error:

1 2 3
var result = UglifyJS.minify({"foo.js" : "if (0) else console.log(1);"}); console.log(JSON.stringify(result.error)); // {"message":"Unexpected token: keyword (else)","filename":"foo.js","line":1,"col":7,"pos":7}

Nota: a diferencia de uglify-js@2.x, la 3.xAPI no arroja errores. Para lograr un efecto similar se podría hacer lo siguiente:

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

Minimizar opciones

  • warnings(predeterminado false): pasa truepara devolver las advertencias del compresor en result.warningsUtilice el valor "verbose"para advertencias más detalladas.

  • parse(predeterminado {}): pase un objeto si desea especificar algunas opciones de análisis adicionales .

  • compress(predeterminado {}): pase falsepara omitir la compresión por completo. Pase un objeto para especificar opciones de compresión personalizadas .

  • mangle(predeterminado true): pase falsepara omitir nombres de manipulación o pase un objeto para especificar opciones de manipulación (ver más abajo).

    • mangle.properties(predeterminado false): una subcategoría de la opción de mangle. Pase un objeto para especificar opciones de propiedad de mangle personalizadas .
  • output(predeterminado null): pase un objeto si desea especificar opciones de salida adicionales . Los valores predeterminados están optimizados para una mejor compresión.

  • sourceMap(predeterminado false): pase un objeto si desea especificar opciones del mapa de origen .

  • toplevel(predeterminado false): configúrelo truesi desea habilitar la modificación de nombres de funciones y variables de nivel superior y eliminar variables y funciones no utilizadas.

  • nameCache(predeterminado null): pase un objeto vacío {}o un nameCacheobjeto utilizado anteriormente si desea almacenar en caché los nombres de variables y propiedades alteradas en múltiples invocaciones de minify(). 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(predeterminado false): configurado para trueadmitir IE8.

  • keep_fnames(predeterminado: false): pasa truepara evitar el descarte o la alteración de nombres de funciones. Útil para código que depende de Function.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 8
var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, { sourceMap: { filename: "out.js", url: "out.js.map" } }); console.log(result.code); // minified output console.log(result.map); // source map

Tenga en cuenta que el mapa de origen no se guarda en un archivo, simplemente se devuelve en result.map. El valor pasado sourceMap.urlsolo se usa para establecer //# sourceMappingURL=out.js.mapen result.code. El valor de filenamesolo se usa para establecer fileel atributo (consulte la especificación ) en el archivo de mapa de origen.

Puede configurar la opción sourceMap.urlpara 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 6
var 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 7
var result = UglifyJS.minify({"compiled.js": "compiled code"}, { sourceMap: { content: "content from compiled.js.map", url: "minified.js.map" } }); // same as before, it returns `code` and `map`

Si en su lugar estás usando el X-SourceMapencabezado, puedes simplemente omitirlo sourceMap.url.

Opciones de análisis

  • bare_returns(predeterminado false): admite returndeclaraciones de nivel superior

  • html5_comments(por defecto true)

  • shebang(predeterminado true): soporte #!commandcomo primera línea

Opciones de compresión

  • arguments(predeterminado true:): reemplácelo arguments[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:): trueaplica optimizaciones para if-s y expresiones condicionales

  • dead_code(predeterminado: true): elimina el código inalcanzable

  • drop_console(predeterminado: false) -- Pasar truepara descartar llamadas a console.*funciones. Si desea descartar una llamada de función específica, como console.infoy/o conservar los efectos secundarios de los argumentos de la función después de descartar la llamada de función, utilice pure_funcsen su lugar.

  • drop_debugger(predeterminado: true) -- eliminar debugger;declaraciones

  • evaluate(predeterminado: true) -- intenta evaluar expresiones constantes

  • expression(predeterminado:): falsepase truepara conservar los valores de finalización de las declaraciones del terminal sin return, por ejemplo, en los marcadores.

  • global_defs(predeterminado: {}) - ver compilación condicional

  • hoist_funs(predeterminado: false) -- declaraciones de función de elevación

  • hoist_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 a f(1, 2);. Nota: hoist_props funciona mejor con manglehabilitado, la compressopción passesestablecida en 2o superior y la compressopción toplevelhabilitada.

  • hoist_vars(predeterminado: false) -- vardeclaraciones de elevación (esto es false predeterminado porque parece aumentar el tamaño de la salida en general)

  • if_return(predeterminado: true) -- optimizaciones para if/return y if/continue

  • inline(predeterminado: true) -- llamadas en línea para funcionar con returndeclaración simple/:

    • false--igual que0
    • 0- línea deshabilitada
    • 1-- funciones simples en línea
    • 2-- funciones en línea con argumentos
    • 3-- funciones en línea con argumentos y variables
    • true--igual que3
  • join_vars(predeterminado: true) -- unir vardeclaraciones consecutivas

  • keep_fargs(predeterminado: true): evita que el compresor descarte argumentos de función no utilizados. Lo necesita para el código que se basa en Function.length.

  • keep_fnames(predeterminado: false) - Pasa truepara evitar que el compresor descarte nombres de funciones. Útil para el código que depende de Function.prototype.name. Consulte también: la keep_fnames opción mangle .

  • keep_infinity(predeterminado: false): pase truepara evitar Infinityque se comprima en 1/0, lo que puede causar problemas de rendimiento en Chrome.

  • loops( predeterminado: true): optimizaciones para doy bucles cuando podemos determinar estáticamente la condición.whilefor

  • 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(predeterminado null:) - 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 variable qes no se usa en ningún otro lugar, UglifyJS lo eliminará, pero seguirá manteniendo el Math.floor(a/b), sin saber lo que hace. Puede pasar pure_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 debajo pure_funcs también estén debajo mangle.reservedpara evitar daños.

  • pure_getters(predeterminado: "strict") -- Si pasa truepor esto, UglifyJS asumirá que el acceso a la propiedad del objeto (por ejemplo, foo.baro foo["bar"]) no tiene ningún efecto secundario. Especifique "strict"tratarlo foo.barcomo libre de efectos secundarios solo cuando foosea seguro que no se producirá, es decir, no nullo undefined.

  • 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 de reduce_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(predeterminado true:): 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 en trueentonces el límite predeterminado sequenceses 200. Establecer opción a falseo 0 para deshabilitar. La sequenceslongitud más pequeña es 2. Un sequencesvalor de 1 está protegido para ser equivalente a truey como tal significa 200. En raras ocasiones, el límite de secuencias predeterminado conduce a tiempos de compresión muy lentos, en cuyo caso 20se recomienda un valor de o menos.

  • side_effects(predeterminado: true): pase falsepara 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 eliminar switchramas inalcanzables

  • toplevel(predeterminado:): falseelimine funciones sin referencia ( "funcs") y/o variables ( "vars") en el alcance del nivel superior ( falsede forma predeterminada, truepara eliminar funciones y variables sin referencia)

  • top_retain(predeterminado:) null: evita que se eliminen funciones y variables de nivel superior específicas unused(pueden ser una matriz, separadas por comas, expresiones regulares o funciones. Implica toplevel) .

  • typeofs(predeterminado: true) - Se transforma typeof foo == "undefined"en foo === void 0Nota: se recomienda establecer este valor falseen 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 como a <= basumir que ninguno de los operandos puede ser (obligado a hacerlo) NaN.

  • unsafe_Function(predeterminado: false): comprime y destroza Function(args, code) cuando ambos argsy codeson literales de cadena.

  • unsafe_math(predeterminado: false): optimiza expresiones numéricas como 2 * x * 3into 6 * x, lo que puede dar resultados de punto flotante imprecisos.

  • unsafe_proto(predeterminado false:) - optimiza expresiones como Array.prototype.slice.call(a)en[].slice.call(a)

  • unsafe_regexp(predeterminado false:): habilita la sustitución de variables con RegExpvalores de la misma manera que si fueran constantes.

  • unsafe_undefined(predeterminado: false): sustituir void 0si hay una variable nombrada undefineden 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(predeterminado false:): muestra advertencias cuando se elimina código inalcanzable o declaraciones no utilizadas, etc.

Opciones de destrucción

  • eval(predeterminado false): pasa truepara modificar los nombres visibles en los ámbitos donde se utilizan evalo .with

  • keep_fnames(predeterminado false) - Pasar truepara no alterar los nombres de las funciones. Útil para el código que depende de Function.prototype.name. Consulte también: la keep_fnames opción de compresión .

  • reserved(predeterminado []): pasa una serie de identificadores que deben excluirse de la manipulación. Ejemplo: ["foo", "bar"].

  • toplevel(predeterminado false): pasa truepara 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 10
var code = fs.readFileSync("test.js", "utf8"); UglifyJS.minify(code).code; // 'function funcName(a,n){}var globalVar;' UglifyJS.minify(code, { mangle: { reserved: ['firstLongName'] } }).code; // 'function funcName(firstLongName,a){}var globalVar;' UglifyJS.minify(code, { mangle: { toplevel: true } }).code; // 'function n(n,a){}var a;'

Mangle properties options

  • builtins(predeterminado: false): se utiliza truepara 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(predeterminado false:): solo modifica los nombres de propiedades sin comillas.

  • regex(predeterminado null:): 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 la reservedmatriz.

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(predeterminado false): caracteres Unicode de escape en cadenas y expresiones regulares (afecta a las directivas con caracteres no ASCII que dejan de ser válidos)

  • beautify(predeterminado true): si realmente se debe embellecer la salida. Pasar -bestablecerá esto en verdadero, pero es posible que necesites pasar -bincluso cuando quieras generar código minimizado, para especificar argumentos adicionales, para que puedas usarlos -b beautify=falsepara anularlo.

  • braces(predeterminado false): siempre inserte llaves en las declaraciones if,, o , incluso forsi su cuerpo es una sola declaración.dowhilewith

  • comments(predeterminado false): pasa trueo "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 defecto 4)

  • indent_start(predeterminado 0): prefije todas las líneas con esa cantidad de espacios

  • inline_script(predeterminado true): escapa de los comentarios HTML y la barra diagonal en las apariciones de </script>cadenas

  • keep_quoted_props(predeterminado false): cuando está activado, evita eliminar las comillas de los nombres de propiedades en los literales de los objetos.

  • max_line_len(predeterminado false): longitud máxima de línea (para código feo)

  • preamble(predeterminado null): 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(predeterminado false): pasa truepara conservar líneas, pero solo funciona si beautifyestá configurado en false.

  • quote_keys(predeterminado false): pasa truepara citar todas las claves en objetos literales

  • quote_style(predeterminado 0): 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. 0Es mejor para el tamaño gzip.
    • 1-- utilice siempre comillas simples
    • 2-- utilice siempre comillas dobles
    • 3-- utilice siempre las comillas originales
  • semicolons(predeterminado true): declaraciones separadas con punto y coma. Si lo aprueba, falsesiempre 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(predeterminado true): conserva shebang #!en el preámbulo (scripts de bash)

  • webkit(predeterminado false): habilita soluciones para errores de WebKit. Los usuarios de PhantomJS deben configurar esta opción en true.

  • width(predeterminado 80): 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(predeterminado false): pasa truepara ajustar las expresiones de función invocadas inmediatamente. Consulte el n.° 640 para obtener más detalles.

Misceláneas

Puede pasar --commentspara 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 allpara 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 7
function f() { /** @preserve Foo Bar */ function g() { // this function is never called } return something(); }

Aunque tenga "@preserve", el comentario se perderá porque gel 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 compressopció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)o Array(1, 2, 3)[ 1, 2, 3 ]
  • new Object(){}
  • String(exp)o exp.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 3
if (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=falsepara 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.jsarchivo con lo siguiente:

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

y construye tu código así:

1
uglifyjs 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 constdeclaraciones si las usa. Si se dirige a entornos <ES6, lo cual no no es compatible const, usar varwith 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_defsy es una propiedad del compresor:

1 2 3 4 5 6 7 8
var result = UglifyJS.minify(fs.readFileSync("input.js", "utf8"), { compress: { dead_code: true, global_defs: { DEBUG: false } } });

Para reemplazar un identificador con una expresión arbitraria no constante, es necesario anteponer la global_defsclave con "@"para indicarle a UglifyJS que analice el valor como una expresión:

1 2 3 4 5 6 7 8
UglifyJS.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 8
UglifyJS.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 TreeWalkery 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:

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

La -p spidermonkeyopció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 acornopció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 compresspara 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:

1
uglifyjs file.js -m

Para habilitar el modo de minificación rápida con el uso de API:

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

Mapas fuente y depuración.

Se sabe que varias compresstransformaciones 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 compressy 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.
  • undefinedy NaNno Infinityhan sido redefinidos externamente.
  • arguments.calleey no se utilizan arguments.caller.Function.prototype.caller
  • El código no espera que el contenido Function.prototype.toString()sea Error.prototype.stacknada en particular.
  • Obtener y configurar propiedades en un objeto simple no causa otros efectos secundarios (usando .watch()o Proxy).
  • 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()