Minificador de JavaScript

Comprime el código JavaScript eliminando comentarios, espacios y caracteres innecesarios.

Acerca de la minificación JavaScript

JavaScript es el tipo de recurso más pesado en la mayoría de páginas web, y no solo porque suele ser el archivo más grande. El coste se reparte en cinco etapas: descarga (por la red), análisis (el motor lee los bytes y construye un AST), compilación (V8 o JavaScriptCore compila el AST a bytecode), ejecución (el bytecode se ejecuta), y en visitas posteriores, arranque en caliente desde el bytecode en caché si el motor lo conservó. Brotli en el borde del CDN gestiona el coste de descarga. La minificación también ayuda con la descarga, pero ayuda igualmente con el análisis y la compilación en cada dispositivo que descarga tu script, y en un teléfono Android de gama baja, el análisis y la compilación pueden tardar más que la transferencia de red. Los artículos Cost of JavaScript de Addy Osmani han demostrado repetidamente que lo que parece un problema de red es a menudo un problema de CPU, y que la reducción del 20-40% en bytes por la minificación se traduce con bastante exactitud en milisegundos ahorrados de tiempo de análisis en la larga cola de dispositivos lentos.

La optimización de análisis perezoso de V8 difiere el análisis completo de cualquier función hasta que se la llama realmente, lo que significa que un script grande con muchas funciones no usadas cuesta menos de lo que sugiere su tamaño en bytes. La caché HTTP de Chrome también almacena el bytecode V8 (la "Code Cache") para que las visitas repetidas se salten enteramente la etapa de análisis y compilación. Nada de esto cambia la ecuación básica: los scripts más pequeños llegan a la caché caliente más rápido, se analizan más rápido en el camino frío y se compilan más rápido. La minificación es el lugar más barato de toda la pila para recuperar milisegundos.

Los cuatro (o cinco) niveles de minificación de JavaScript

No todos los minificadores son iguales, y el nivel que necesitas depende de tu base de código. Nivel 1: eliminación de espacios y comentarios. El paso más sencillo, eliminar espacios, tabulaciones, saltos de línea y comentarios // ... / /* ... */. Esto es lo que un paso por regex puede hacer con seguridad (con cuidado alrededor de cadenas, literales de plantilla y literales regex). Reducción típica: 20-40% en bytes brutos. Nivel 2: renombrado de símbolos (mangling). Los nombres de variables locales, los parámetros de función y (con cuidado) los nombres de función se reescriben en letras únicas: function calculateTotal(itemList) se convierte en function a(b). Esto requiere un Árbol de Sintaxis Abstracta y un análisis completo del ámbito para saber qué nombres son seguros de renombrar, los nombres globales, los exports, las referencias a las propiedades de this, y todo lo que se alcanza mediante acceso por clave de cadena (obj['name']) deben permanecer intactos. Reducción adicional típica: 10-25%. Nivel 3: eliminación de código muerto (tree shaking). El análisis estático a nivel de módulo identifica imports y rutas de código que nunca se ejecutan y los elimina. Requiere información de tipos a nivel de módulo y una comprensión clara de los efectos secundarios. Reducción adicional típica: variable, pero puede ser enorme en bibliotecas que envían muchas funciones. Nivel 4: inlining y plegado de constantes. Las expresiones simples como 2 * 60 * 60 se evalúan en tiempo de compilación a 7200; las funciones diminutas llamadas una sola vez pueden integrarse en su llamante. Nivel 5: mangling de propiedades. La optimización más agresiva, los nombres de propiedades de objeto también se reescriben. Rompe cualquier código que use claves de cadena (obj['name'] vs obj.name) o que exponga nombres de propiedades como parte de su contrato público. Casi siempre opt-in y casi siempre limitado a identificadores específicos mediante una regex --mangle-props.

Una breve historia de las herramientas de minificación de JavaScript

JSMin (2003). Douglas Crockford, sí, el mismo Crockford que promovió JSON, escribió JSMin en C en 2003. Era un programa diminuto de un solo archivo que hacía una eliminación básica de espacios y comentarios sin AST, sin análisis de ámbito y con un enfoque deliberadamente conservador de los casos límite de ASI (Automatic Semicolon Insertion). Estableció el listón de "la cosa más sencilla que funciona" y es el antepasado espiritual de todo minificador de JS basado en regex desde entonces. YUI Compressor (2007). Julien Lecomte de Yahoo anunció YUI Compressor el 11 de agosto de 2007. Usaba el tokenizador Rhino para hacer un renombrado seguro de símbolos, la primera herramienta Java ampliamente usada que hacía verdadero mangling basado en AST para JavaScript. Closure Compiler (2009). Google lo había usado internamente desde 2005; lo abrieron bajo Apache 2.0 el 5 de noviembre de 2009. Closure era el optimizador más agresivo de la época, consciente de los tipos a través de anotaciones JSDoc, con un modo "advanced" que podía reescribir nombres de propiedades basándose en inferencia de tipos. La contrapartida era que tenías que escribir tu código de forma compatible con Closure; los fallos del modo avanzado eran notorios.

UglifyJS (~2010-2012). UglifyJS de Mihai Bazon fue el primer minificador nativo de JavaScript, escrito en JS, ejecutado en Node.js, y se convirtió en el predeterminado de npm durante una década. UglifyJS 2 añadió soporte para source maps y características de ES5; UglifyJS 3 continuó con pulido de ES5 pero nunca obtuvo soporte completo para ES6+. Terser (agosto de 2018). Fabricio Matté bifurcó UglifyJS en Terser específicamente para añadir soporte ES6+ sin alterar la estable API de UglifyJS. Terser es ahora el minificador JS por defecto en webpack 5, Rollup, Parcel 1 y las versiones más antiguas de Next.js. swc (2017/2019). swc de Donny "kdy1" Choi ("Speedy Web Compiler") es un compilador JavaScript/TypeScript basado en Rust con un minificador integrado 20-70x más rápido que Terser. Next.js cambió su minificador por defecto de Terser a swc a partir de la versión 12 en octubre de 2021. esbuild (invierno 2019-2020). Evan Wallace, cofundador de Figma, lanzó esbuild durante las vacaciones de invierno 2019-2020. Escrito en Go, es 10-100x más rápido que los bundlers basados en JavaScript de la época y trae su propio minificador. esbuild es ahora el minificador subyacente en Vite, en tsup y en muchas plantillas de framework. La dirección general en los últimos cinco años ha sido: parser escrito en un lenguaje de sistemas rápido (Rust o Go), optimizaciones basadas en AST, tree shaking inteligente consciente de módulos ES. El minificador regex pegado en el navegador, como esta herramienta, se sitúa al final de esa escalera, haciendo el trabajo más simple que aún es útil.

Source maps para JavaScript minificado

Un source map es un archivo JSON adjunto que mapea posiciones en la salida minificada a posiciones en la fuente original. La especificación Source Map V3 fue redactada por John Lenz (Google) y Nick Fitzgerald (Mozilla) en 2011, y fue adoptada por TC39 como ECMA-426 en junio de 2024, el mismo formato de source map se aplica tanto a JavaScript como a CSS. Los navegadores consumen el mapa a través de un comentario al final del archivo minificado: //# sourceMappingURL=app.js.map. Cuando DevTools está abierto y el mapa se obtiene, el panel Fuentes muestra la fuente original, con puntos de interrupción, errores de consola y trazas de pila refiriéndose todos a ella. Los minificadores de producción (Terser, swc, esbuild, Closure) todos emiten source maps a petición. Esta herramienta no, para una herramienta one-shot en el navegador que devuelve texto en lugar de un par de archivos descargables, los source maps añaden una complejidad significativa por un beneficio marginal. La divulgación honesta es que esta herramienta es un paso unidireccional; los minificadores de pipeline de build tienen un argumento mucho más sólido para los source maps porque las fuentes originales están en disco y el desarrollador necesita depurar en tiempo de ejecución.

Configuraciones por defecto de los bundlers modernos, la mayoría ya tiene un minificador

Si usas un pipeline de build moderno, tu minificador ya se está ejecutando. webpack 5 usa terser-webpack-plugin con Terser por defecto. Vite usa esbuild para minificación por defecto; Lightning CSS para CSS. Parcel usa swc. Next.js cambió de Terser a swc en v12 (octubre de 2021), y de Babel a swc para todo el pipeline de build en la misma versión. Remix, Astro, SvelteKit, Nuxt, Rollup, esbuild independiente, todos integran la minificación en las builds de producción sin intervención del desarrollador. El resultado es que para cualquiera que use un pipeline de build moderno, la minificación de JS ocurre automáticamente con optimizaciones muy por encima de lo que una herramienta de un solo archivo basada en regex puede hacer. Los casos en que este minificador en el navegador se gana su lugar: páginas HTML hechas a mano con bloques <script> inline; temas de WordPress entregados sin cadena de herramientas Node; generadores de sitios estáticos que no integran minificación; fragmentos puntuales pegados en un CMS o plantilla de correo; experimentos rápidos donde montar un pipeline de build llevaría más tiempo que el propio script.

Alcance honesto: lo que esta herramienta hace y no hace

Esta herramienta es un minificador basado en regex, aproximadamente 30 líneas de JavaScript. Tokeniza literales de cadena, literales de plantilla y literales regex en placeholders para que las transformaciones posteriores no puedan corromper su contenido; elimina comentarios // ... y /* ... */; colapsa secuencias de espacios; elimina espacios alrededor de puntuación que no los necesita; y restaura los literales tokenizados. La salida típica es 20-40% más pequeña que la entrada en bytes brutos. Lo que esta herramienta no hace, y que sí manejan los minificadores de producción (Terser, swc, esbuild, Closure): no renombra variables locales a letras únicas (sin mangling consciente del ámbito); no realiza eliminación de código muerto ni tree-shaking; no realiza plegado de constantes ni simplificación de expresiones; no emite source maps; no entiende la sintaxis de TypeScript (pega solo JavaScript puro); no hace tree-shake de imports de módulos ES; no reescribe nombres de propiedades. El encuadre honesto: pega el JavaScript que salió de tu editor o de tu mano, recupera una versión despojada que es típicamente 20-40% más pequeña en bytes brutos, y úsala como artefacto de despliegue rápido. Para proyectos con un pipeline de build, usa Terser, swc o esbuild en ese pipeline; las optimizaciones conscientes de AST son la diferencia entre la reducción del 20-40% de esta herramienta y el 60-80% de un minificador de producción.

Las trampas del minificador regex

Un paso basado en regex que no entiende la gramática de JavaScript puede corromper el código de formas sutiles. Las trampas clásicas: los literales de plantilla usan backticks y pueden contener expresiones interpoladas (`Hello ${name}!`) que parecen candidatas para eliminación de comentarios si la regex no es cuidadosa. Los literales regex como /^\/\*/g contienen barras inclinadas, secuencias parecidas a comentarios y contenido parecido a cadenas; manejarlos mal convierte una regex en código sintácticamente roto. Las cadenas que contienen texto parecido a comentarios (const url = "// example.com"), la eliminación ingenua de comentarios eliminaría todo después del //. Las trampas de ASI, Automatic Semicolon Insertion es la característica de JS que te permite omitir punto y coma la mayor parte del tiempo, pero interactúa mal con la eliminación de espacios cuando el siguiente token empieza con paréntesis, corchete u operador ((/regex/), [arr], +1), un colapso de espacios imprudente puede convertir "dos sentencias" en "una sentencia con error de análisis". La mitigación en esta herramienta es el paso de tokenización de literales que se ejecuta primero, reemplazando cada cadena y regex con un placeholder único, haciendo el trabajo de comentarios+espacios sobre el código limpio, y luego restaurando los placeholders. No es perfecto, pero cubre los casos comunes. Si sospechas que el minificador rompió tu código, lo primero que comprobar es un literal regex que contenga una secuencia de barra que el tokenizador haya pasado por alto.

Privacidad: por qué solo navegador importa aquí

Los minificadores JS del lado del servidor (herramientas en línea que envían tu código por POST a un servidor, lo pasan por Terser allí y devuelven el resultado) requieren subir tu fuente. Para código de biblioteca ordinario esto es inofensivo. Para herramientas internas, código de producto no lanzado, JavaScript que contiene claves API en línea o credenciales de servicios de terceros, o cualquier código que revele algoritmos propietarios o lógica de negocio, no lo es. Un minificador puramente basado en el navegador, JavaScript ejecutándose en tu pestaña que nunca hace una petición de red después de la carga inicial de la página, evita el problema. Puedes verificarlo abriendo la pestaña Red de DevTools, pegando el código, haciendo clic en Minificar y observando cualquier petición saliente. Mejor aún, desconéctate de Internet (o activa el modo avión) después de que la página cargue y la herramienta seguirá funcionando, lo que es la prueba empírica más sólida de que nada se está subiendo.

Preguntas frecuentes

¿Cuánto más pequeño será mi código?

Para código formateado a mano con comentarios e indentación, espera una reducción de tamaño del 20-40% en bytes brutos. Los minificadores de producción (Terser, swc, esbuild) con optimizaciones AST completas alcanzan 60-80%, la diferencia es el renombrado de símbolos, la eliminación de código muerto y el plegado de constantes, ninguno de los cuales una herramienta solo regex puede hacer con seguridad. Tras compresión Brotli en el borde del CDN, el ahorro adicional de la minificación es más modesto (5-15% más allá de Brotli sobre el original sin minificar) pero no es cero, y a escala se suma.

¿La salida minificada romperá mi código?

Para la gran mayoría de código, no. Los casos límite conocidos son alrededor de literales regex con secuencias de barra (/foo\/bar/), literales de plantilla con interpolaciones incrustadas que abarcan varias líneas, y contextos de Automatic Semicolon Insertion donde eliminar un salto de línea cambia el análisis. El paso de tokenización de literales de la herramienta maneja los casos comunes, pero si tu código es inusualmente denso en cualquiera de esos patrones, prueba la salida minificada en un navegador antes de desplegar. Para un pipeline de build de producción, usa Terser o swc, tienen conciencia AST completa y manejan estos casos correctamente.

¿Esta herramienta renombra variables?

No. El mangling de variables, convertir function calculateTotal(itemList) en function a(b), requiere análisis completo del ámbito sobre un AST para saber qué nombres son seguros de renombrar. Un paso por regex no puede hacer esto con seguridad. Para renombrado de símbolos, usa Terser, UglifyJS o swc en un pipeline de build; implementan mangling consciente del ámbito correctamente. La reducción de tamaño adicional del 10-25% que produce es real y vale la pena hacerla para código de producción.

¿Puedo pegar TypeScript?

No, esta herramienta es un minificador solo de JavaScript. TypeScript añade anotaciones de tipo (function add(a: number, b: number): number), interfaces, enums, decoradores y otra sintaxis que no es JavaScript válido. Compila primero tu TypeScript a JavaScript usando tsc, swc, esbuild o Babel, luego pega la salida JavaScript aquí. La mayoría de proyectos TypeScript ya pasan por uno de esos compiladores como parte del build, así que el JavaScript existe en algún lugar.

¿Debería usar esto si ya tengo un pipeline de build?

Probablemente no, tu bundler está haciendo esto por ti, con optimizaciones basadas en AST muy por encima de lo que una herramienta regex puede ofrecer. webpack 5 trae terser-webpack-plugin con Terser; Vite usa esbuild para JS por defecto; Parcel usa swc; Next.js ha usado swc desde v12 (octubre de 2021). Esta herramienta es para los casos que tu pipeline de build no cubre: páginas HTML hechas a mano, temas de WordPress entregados sin cadena de herramientas Node, generadores de sitios estáticos que no integran minificación, fragmentos puntuales, o experimentos rápidos donde montar un build llevaría más tiempo que el propio script.

¿Se suben mis archivos?

No. El minificador es JavaScript ejecutándose en tu navegador. El código que pegas nunca cruza la red, verifícalo en la pestaña Red de DevTools mientras haces clic en Minificar, o desconecta la página después de que cargue y confirma que la herramienta sigue funcionando. Las herramientas internas, el código de producto no lanzado, los scripts que contienen claves API en línea o lógica de negocio propietaria permanecen en tu dispositivo.

Herramientas relacionadas