Impresionante módulo de comunidad

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 con uglify-js@2 .
  • La documentación para las versiones de UglifyJS 2.x se puede encontrar aquí .
  • uglify-js solo admite JavaScript (ECMAScript 5).
  • To minify ECMAScript 2015 or above , transpile utilizando herramientas como Babel .

Instalar en pc

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:

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 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:

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

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 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 del 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

--compress pasar --compress ( -c ) para habilitar el compresor. Opcionalmente, puede pasar una lista de opciones de compresión separadas por comas.

Las opciones tienen 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:

1
uglifyjs file.js -c toplevel,sequences=false

Opciones de cambio de CLI

Para habilitar el administrador, debe pasar --mangle ( -m ). Se --mangle siguientes opciones (separadas por comas):

  • toplevel (valor predeterminado false ): nombres de manipulación declarados en el ámbito de nivel superior.

  • eval (valor predeterminado false ): nombres de manipulación visibles en ámbitos donde se utilizan eval o with .

Cuando la función de selección está habilitada pero desea evitar que ciertos nombres se alteren, 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 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 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
1
var 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_]
1
var 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=/_$/
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 utilidad, evitamos alterar los nombres estándar de JS de forma predeterminada ( --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.

El uso del nombre de caché no es necesario 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 propiedad entre comillas ( o["foo"] ) reserva el nombre de propiedad ( foo ) para que no se altere en todo el script, incluso cuando se usa 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
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 debug para alterar los nombres de 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
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 o.foo a o._$foo$XYZ_ . Puede cambiar esto cada vez que compila un script para identificar cómo se destrozó una propiedad 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:

1
var 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 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 minify más de un archivo JavaScript a la vez utilizando un objeto para el primer argumento donde las claves son nombres de archivo 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 opción de nivel toplevel :

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 opción nameCache :

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 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 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 opciones minify() :

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 , the API 3.x` 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;

Minificar opciones

  • warnings (valor predeterminado false ): pase true para devolver las advertencias del compresor en result.warnings . Utilice el valor "verbose" para obtener advertencias más detalladas.

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

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

  • mangle (valor predeterminado true ): pasar false para omitir nombres de cambio, o pasar un objeto para especificar opciones de cambio (ver más abajo).

    • mangle.properties (valor predeterminado false ): 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 la mejor compresión.

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

  • toplevel (valor predeterminado false ) toplevel a true 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 objeto nameCache usado anteriormente si desea almacenar en caché los nombres de variables y propiedades destrozadas en múltiples invocaciones de minify() . 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 predeterminado false ) -conjunto a true para admitir IE8.

  • keep_fnames (predeterminado: false ) -pass true para evitar descartar o alterar los nombres de las funciones. Útil para el código que se basa en Function.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 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 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 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, 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 está utilizando el encabezado X-SourceMap , puede omitir sourceMap.url .

Opciones de análisis

  • bare_returns (valor predeterminado false ): admite declaraciones de return nivel superior

  • html5_comments (valor predeterminado true )

  • shebang ( true predeterminado): #!command como primera línea

Opciones de compresión

  • arguments (valor predeterminado: true ): reemplace 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 (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 ejemplo a = !b && !c && !d && !e → a=!(b||c||d||e) etc.

  • conditionals (valor predeterminado: true ): aplique optimizaciones para if -s y expresiones condicionales

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

  • drop_console (por defecto: false ) - Pase true para descartar llamadas a la console.* funciones. Si desea descartar una llamada a una función específica como console.info y / o retener los efectos secundarios de los argumentos de la función después de pure_funcs llamada a la función, use pure_funcs en lugar.

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

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

  • expression (predeterminado: false ): pase true para preservar los valores de finalización de las declaraciones de terminal sin return , por ejemplo, en marcadores.

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

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

  • hoist_props (predeterminado: true ): hoist_props propiedades 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 a f(1, 2); Nota: hoist_props funciona mejor con la función de mangle habilitada, la opción de compress passes establecida a 2 o superior, y la opción de compress toplevel habilitado.

  • hoist_vars (por defecto: false ): hoist_vars declaraciones de var (esto es false por defecto 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 una declaración simple / return :

    • false - igual que 0
    • 0 - en 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 que 3
  • join_vars (predeterminado: true ): une sentencias var consecutivas

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

  • keep_fnames (predeterminado: false ): pase true para evitar que el compresor descarte los nombres de funciones. Útil para el código que se basa en Function.prototype.name . Consulte también: la opción de keep_fnames .

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

  • loops (predeterminado: true ): optimizaciones para do , while y for bucles cuando podemos determinar estáticamente la condición.

  • negate_iife (valor predeterminado: true ): niega las "Expresiones de funciones negate_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 ): reescribe el acceso a la propiedad utilizando la notación de puntos, por ejemplo foo["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 ejemplo var q = Math.floor(a/b) . Si la variable q no se usa en otro lugar, UglifyJS la soltará, pero seguirá manteniendo 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 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 bajo pure_funcs también bajo mangle.reserved para evitar destrozos.

  • pure_getters (predeterminado: "strict" ): si pasa true para esto, UglifyJS asumirá que el acceso a la propiedad del objeto (por ejemplo, foo.bar o foo["bar"] ) no tiene ningún efecto secundario. Especifique "strict" para trate foo.bar como libre de efectos secundarios solo cuando es seguro que foo no lanzará, es decir, no será null o undefined .

  • reduce_funcs (predeterminado: true ): permite que las funciones de un solo uso se inserten como expresiones de función cuando sea permisible, lo que permite una mayor optimización. Habilitado de forma predeterminada. La opción depende de la reduce_vars de los reduce_vars habilitación. 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 ): mejora la optimización de las variables asignadas y utilizadas como valores constantes.

  • sequences (predeterminado: true ): une 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 en true , el límite de sequences predeterminado es 200 Establezca la opción en false o 0 para deshabilitarla. La longitud de sequences más pequeña es 2 Un valor de sequences de 1 es equivalente a true y, como tal, significa 200 En raras ocasiones, el límite predeterminado de secuencias conduce a tiempos de compresión muy lentos. en cuyo caso se recomienda un valor de 20 o menos.

  • side_effects (predeterminado: true ): pase false para deshabilitar las funciones potencialmente descartadas marcadas como "puro". Una llamada de función se marca como "pura" si una anotación de comentario /*@__PURE__*/ o /*#__PURE__*/ inmediatamente precede a llamada. Por ejemplo: /*@__PURE__*/foo();

  • switches (predeterminado: true ): desduplica y elimina ramas de switch inalcanzables

  • toplevel (predeterminado: false ): descartar 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 (valor predeterminado: null ): evita que las funciones y variables específicas de nivel top_retain unused (puede ser matriz, separadas por comas, RegExp o función. Implica nivel toplevel )

  • typeofs (predeterminado: true ): transforma typeof foo == "undefined" en foo === void 0 Nota: se recomienda establecer este valor en false para 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 <= b suponiendo que ninguno de los operandos puede ser (coaccionado) a NaN .

  • unsafe_Function (valor predeterminado: false ): comprime y destruye la Function(args, code) cuando tanto args como code son literales de cadena.

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

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

  • unsafe_regexp (predeterminado: false ): habilita las sustituciones de variables con valores RegExp la misma manera que si fueran constantes.

  • unsafe_undefined (predeterminado: false ): sustituya void 0 si hay una variable denominada undefined en alcance (el nombre de la variable se desbaratará, generalmente se reducirá a un solo carácter)

  • unused (predeterminado: true ): descarta 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 al soltar código inalcanzable o declaraciones no utilizadas, etc.

Opciones de mangle

  • eval (valor predeterminado false ): pase true a los nombres de manipulación visibles en los ámbitos donde se utilizan eval o with .

  • keep_fnames (valor predeterminado false ): pase true para no alterar nombres de funciones. Útil para el código que se basa en Function.prototype.name . Consulte también: la opción de compresión keep_fnames .

  • reserved (predeterminado [] ) - Pase una matriz de identificadores que deberían excluirse de la manipulación. Ejemplo: ["foo", "bar"] .

  • toplevel (valor predeterminado false ): pase true a los nombres de destrucción 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 (valor predeterminado: false ): use true 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 propiedad que coincidan con la expresión regular.

  • reserved (predeterminado: [] ): no altere los nombres de propiedades que figuran en la matriz reserved .

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 (valor predeterminado false ): escapa de los caracteres Unicode en cadenas y expresiones regulares (afecta a las directivas con caracteres no ascii que no son válidos)

  • beautify (valor predeterminado true ): si se debe embellecer realmente 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, de modo que pueda use -b beautify=false para anularlo.

  • braces (valor predeterminado false ): siempre inserte llaves en if , for , do , while o with declaraciones, incluso si su cuerpo es una sola declaración.

  • comments (valor predeterminado false ): pase true o "all" para conservar todos los comentarios, "some" para conservar algunos comentarios, una cadena de expresión regular (por ejemplo, /^!/ ) o una función.

  • indent_level (predeterminado 4 )

  • indent_start (predeterminado 0 ): prefija todas las líneas por tantos espacios

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

  • keep_quoted_props (valor predeterminado false ): cuando está activado, evita que se eliminen las comillas de los nombres de propiedad en literales de objeto.

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

  • preamble ( null predeterminado): cuando se pasa, debe ser una cadena y se antepondrá a la salida literalmente. El mapa de origen se ajustará para este texto. Se puede utilizar para insertar un comentario que contenga información de licencia, por ejemplo.

  • preserve_line (valor predeterminado false ): pase true para preservar líneas, pero solo funciona si beautify se establece en false .

  • quote_keys (valor predeterminado false ): pasar true para citar todas las claves en objetos literales

  • quote_style (valor predeterminado 0 ): estilo de cotización preferido para cadenas (afecta también a los nombres de propiedad y directivas):

    • 0 : prefiere comillas dobles, cambia a comillas simples cuando hay más comillas dobles en la cadena en sí. 0 es el mejor para el tamaño de gzip.
    • 1 - siempre use comillas simples
    • 2 - siempre usa comillas dobles
    • 3 - siempre usa las citas originales
  • semicolons y semicolons (valor predeterminado true ): separe las declaraciones con punto y coma. Si pasa false , 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 significativamente mayor) )

  • shebang ( true predeterminado): preservar shebang #! en el preámbulo (scripts bash)

  • webkit (valor predeterminado false ): habilite soluciones alternativas para los errores de WebKit. Los usuarios de PhantomJS deben establecer 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 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 predeterminado false ): pase true para ajustar las expresiones de función invocadas de inmediato. Consulte # 640 para obtener más detalles.

Diverso

PUEDE pasar por usted - --comments . --comments ciertos comentarios La salida Por defecto en estilo IT mantendrá JSDoc que contenga comentarios "@preserve", "@license" o "@cc_on" (compilación condicional para IE) Pase por You CAN. --comments all para mantener todos los comentarios, o una --comments /^!/ JavaScript válida para mantener solo los comentarios que coincidan con esta --comments /^!/ . Por ejemplo --comments /^!/ mantendrá comentarios como /*! Copyright Notice */ .

Sin embargo, tenga en cuenta que puede haber situaciones en las que se pierden los comentarios, por ejemplo:

1 2 3 4 5 6 7
function f() { /** @preserve Foo Bar */ function g() { // this function is never called } return something(); }

Aunque tiene "@preserve", el comentario se perderá porque el compresor descarta la función interna g (que es el nodo AST al que se adjunta el comentario) como no referenciada.

Los comentarios más seguros sobre dónde colocar la información de copyright (u otra información que debe mantenerse en la salida) son comentarios adjuntos a nodos de nivel superior.

La opción de compress unsafe

Permite algunas transformaciones que pueden romper la lógica del código en ciertos casos artificiales, pero deberían estar bien para la mayoría del código. Es posible que desee probarlo en su 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 el new

Conditional compilation

Puede usar el --define ( -d ) para declarar variables globales que UglifyJS asumirá como constantes (a menos que estén definidas en el alcance). Por ejemplo, si pasa --define DEBUG=false entonces, junto con la eliminación de código muerto UglifyJS descartará lo siguiente de la salida:

1 2 3
if (DEBUG) { console.log("debug stuff"); }

Puede especificar constantes anidadas en forma de --define env.DEBUG=false .

UglifyJS advertirá sobre la condición siempre falsa y sobre la caída de código inalcanzable; por ahora no hay 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 archivo build/defines.js 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 alterar, evaluará las referencias al valor en sí mismo y soltará el código inalcanzable como de costumbre. La compilación contendrá las declaraciones const si las usa. Si está apuntando a entornos <ES6 que no es compatible con const , usar var con reduce_vars (habilitado por defecto) debería ser suficiente.

Conditional compilation API

También puede 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 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 clave global_defs con "@" para indicar 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, se reemplazaría como literal de cadena:

1 2 3 4 5 6 7 8
UglifyJS.minify("alert('hello');", { compress: { global_defs: { "alert": "console.log" } } }).code; // returns: '"console.log"("hello");'

Uso de AST Uglify nativo con minify 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

La transversal y la transformación del AST nativo se pueden realizar a través de 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 interno de SpiderMonkey AST. 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 descarga el AST en JSON en la salida estándar. Para usar UglifyJS para destrozar y comprimir eso:

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

La opción -p spidermonkey spidermonkey le dice a UglifyJS que todos los archivos de entrada no son JavaScript, sino el código JS descrito en SpiderMonkey AST en JSON. Por lo tanto, no usamos nuestro propio analizador en este caso, solo transformamos ese AST en nuestro AST interno.

Use Acorn for parsing

Más por diversión, agregué la opción -p acorn que usará Acorn para hacer todo el análisis. Si pasa esta opción, UglifyJS require("acorn") .

Acorn es realmente rápido (por ejemplo, 250 ms en lugar de 380 ms en un código de 650 K), pero la conversión del á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 se sabe bien, pero la eliminación de espacios en blanco y la manipulación de símbolos representa el 95% de la reducción de tamaño en el código minimizado para la mayoría de las transformaciones de código no elaboradas en JavaScript. Uno puede simplemente deshabilitar la compress para acelerar las compilaciones de Uglify de 3 a 4 veces. mangle modo de solo mangle Uglify tiene velocidades de minificación y tamaños de gzip comparables a butternut :

d3.js tamaño minify tamaño de gzip tiempo minify (segundos)
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 = verdadero, comprimir = falso 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

Para habilitar el modo minify rápido desde el uso de CLI:

1
uglifyjs file.js -m

Para habilitar el modo minify rápido con el uso de API:

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

Mapas de origen y depuración

Se sabe que varias transformaciones de compress que simplifican, reorganizan, alinean y eliminan código tienen un efecto adverso en la depuración con mapas de origen. Esto se espera ya que el código está optimizado y las asignaciones a menudo simplemente no son posibles ya que algunos códigos ya no existen. la depuración del mapa fuente deshabilita la opción de compress Uglify y solo 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 , NaN e Infinity no se han redefinido externamente.
  • arguments.callee , arguments.caller y Function.prototype.caller no se utilizan.
  • El código no espera que el contenido de Function.prototype.toString() o Error.prototype.stack sea ​​algo en particular.
  • Obtener y establecer propiedades en un objeto plano no causa otros efectos secundarios (usando .watch() o Proxy ).
  • Object properties can be added , eliminar y modificar (no se evita con Object.defineProperty() , Object.defineProperties() , Object.freeze() , Object.preventExtensions() o Object.seal() ).