Minimizado de documentos

Figura
Figura. Código HTML minimizado

Con la acción de minimizar documentos quitamos todos los espacios inútiles con objeto de reducir el tamaño del documento. La reducción de tamaño puede ser significativa en algunos casos, tal como comenté en el tema del enlace anterior. En documentos HTML la reducción puede estar en torno al 15%. En documentos JS y CSS la reducción puede superar el 50%.

En su día ya presente la herramienta minimizador (con PHP) con la que venía ejecutando el minimizado de los documentos antes de subirlos al servidor. Últimamente he estado trasladando esas herramientas desde PHP a JavaScript en el marco de herramientas Web Tools Online. Ahora le toca el turno al minimizador de documentos.

Para llevar a cabo un minimizado eficaz necesitamos parsear el documento y obtener el Array de nodos. También se usa el gestor DOM, pues necesitaremos realizar algunas consultas y modificar algunos nodos. El parseador nos permite reconstruir el documento tras las modificaciones, obteniéndose un contenido minimizado que se ajusta a una determinada configuración previa.

Empecemos con un ejemplo simple. Supongamos que tenemos el siguiente código. La cadena de atributos y el texto interior se dispone en el código en varias líneas:

<div id="abc" 
class="pqr xyz">
    Línea 1
    Línea 2
</div>
    

Sabemos que HTML agrupará uno o más espacios del texto convirtiéndolos en un único espacio simple. Así que los saltos de línea del texto interior y los espacios iniciales en cada línea son caracteres inútiles a la hora de renderizar el elemento. Además el salto de línea en la cadena de atributos también está de más, pudiendo convertirse en un espacio simple:

<div id=abc class="pqr xyz">Línea 1 Línea 2</div>
    

Por último podemos prescindir de las comillas de los valores de los atributos cuando no contengan un espacio o algún caracter del grupo "`'=<>/. Esto se llevará a cabo si la opción alwaysQuotes del parseador estuviera desactivada.

Veámos ahora el siguiente código:

<input 
    type="text"
    value="abc"
    disabled="disabled"
/>
    

Al minimizar quitamos espacios y comillas inútiles. Además si la configuración alwaysValues del parseador estuviera desactivada, eliminará el valor del atributo cuando coincida con el nombre, como le sucede al atributo disabled:

<input type=text value=abc disabled />
    

Si fuera el caso de que no quisiéramos eliminar el valor del atributo cuando coincida con el nombre podríamos usar algún caracter Unicode como el espacio de ancho cero. Se trata de la referencia &#x200b; que podríamos agregar a los valores de los atributos value y title del siguiente ejemplo para que no resulten eliminados:

<input 
    type="text"
    value="&#x200b;value"
    title="&#x200b;title"
/>
    

Quedaría minimizado como sigue:

<input type=text value=&#x200b;value title=&#x200b;title />
    

Si por alguna razón no se pueden usar espacios de ancho cero puede cambiar una letra del valor por su referencia al caracter. Por ejemplo &#x76; para la primera letra "v" del valor "value" o &#x74; para la primera letra "t" del valor "title". Recuerde que el navegador convierte todas las referencias a caracteres antes de incorporar el elemento en el DOM y renderizarlo, por lo que esos atributos contendrán finalmente los valores "value" y "title".

Si elegimos como tipo de configuración xhtml en el parseador, esas opciones alwaysQuotes y alwaysValues aparecerán activadas, pues así lo exige XHTML. En ese caso no se eliminarán las comillas ni los valores cuando coincidan con el nombre del atributo.

Opciones para el minimizado de espacios

El resto de opciones para configurar la minimización son las propias del minimizador. En este apartado veremos las relacionadas con la eliminación de espacios inútiles, entendiéndolos como espacios que no se renderizan y por tanto pueden suprimirse en el código. La primera opción es una lista de elementos de bloque entre los cuáles pueden eliminarse esos espacios inútiles. Esos elementos de bloque son algunos como <p>. No lo es un elemento como <em>. Así con un código como el siguiente:

<p>
    1 <em>2</em> 3
</p>
<p>
    4
</p>
    

Si minimizamos el HTML anterior veremos que, aparte de eliminar los espacios iniciales y finales del contenido de los elementos de bloque, también elimina los espacios entre los dos elementos de bloque:

<p>1 <em>2</em> 3</p><p>4</p>
    

Otras dos opciones son también una listas de elementos no minimizables y css no minimizables. No se minimiza el contenido de los elementos <pre> así como elementos con estilo white-space, suponiendo que el valor de ese estilo sea distinto de normal, que es lo esperable. Si minimizamos el código siguiente verá que se respetan los espacios en el interior de estos dos elementos de bloque:

<pre>
   1
   2
</pre>
<div style="white-space: pre">
   1
   2
</div>
    

El estilo white-space: pre también pueden encontrarse como una regla dentro de un elemento <style>, como en este ejemplo:

<style>
    .a {
        white-space: pre;
    }
    #b {
        white-space: pre;
    }
</style>
<div class="a">
   1
   2
</div>
<div id="b">
   1
   2
</div>
    

Vemos que no se minimizan los elementos con CLASS o ID que tenga ese estilo:

<style>.a{white-space:pre}#b{white-space:pre}</style><div class=a>
   1
   2
</div><div id=b>
   1
   2
</div>
    

Por último podemos forzar a que un elemento se minimize siempre si porta un atributo data-minimize="true". Y para forzar a que no se minimice nunca usaremos el valor "false" en ese atributo. Para ello debemos activar la opción usar atributo data-minimize, como hemos usado para este ejemplo:

<pre data-minimize="true">
   1
   2
</pre>
<div data-minimize="false">
   1
   2
</div>
    

donde el <pre> será minimizado y el <div> no lo será:

<pre data-minimize=true>1 2</pre><div data-minimize=false>
   1
   2
</div>
    

Verificar código JS y PHP

Como hemos visto, se minimizan los espacios del contenido de todos los elementos a excepción de los señalados en el apartado anterior. Se exceptúan los elementos escapable raw text que se definen en la herramienta Parseador XML, con elementos como <textarea> y <title>. En cambio los raw text elements como <script> y <style> se minimizan siempre.

Pero además para los JS Y PHP podemos activar la opción verificar scripts. Si se activa, al finalizar el minimizado de esos códigos se procede a revisar varios aspectos relacionados con la corrección del código, como por ejemplo que dos sentencias estén correctamente separadas. Este chequeo no pretende ser ni de lejos una revisión de la sintaxis del código. Sólo se revisan algunos aspectos que pudieran dar lugar a errores de sintaxis tras el minimizado.

Por ejemplo, con este código nos dará un error de que hay una falta de separación entre ambas sentencias pues falta el punto y coma de la primera línea. Si minimizaramos eliminando el salto de línea entre ellas se produciría un error de sintaxis:

var abc = "abc"
var def = 123;
    

Otro aspecto que chequeamos es que no puede haber un salto de línea antes de la flecha de una función flecha. Si minimizamos el siguiente JS nos dirá que no puede haber un salto antes de "=> 789":

let foo = () => 123;  // Sentencia correcta
let bar = () => 
          456;  // Sentencia correcta
let baz = () 
          => 789;  // Sentencia incorrecta
    

También se revisa la aparición de barras derechas en ciertas condiciones. Veámos antes que una expresión regular en JS podría ser como let reg = /x/ teniendo como mínimo un caracter entre las barras. No puede tener cero caracteres pues entonces sería una doble barra de comentario. Cuando hay que representar un expresión regular vacía se usa un grupo de captura vacío como let reg = /(?:)/. Pero si la expresión es let reg = / / con un único caracter espacio entre las barras nos emitirá un aviso de que ese espacio intermedio será eliminado, pues una de las cosas que hace el minimizador es eliminar espacios entre operadores. Y la barra derecha se considera un operador. Avisa de eso diciendo que podemos cambiar la expresión anterior por let reg = /[ ]/ con el mismo efecto y sin que se minimice ese espacio pues los corchetes no son operadores.

Por último veamos otro aspecto con dos operadores "++" o "--" seguidos. El siguiente código es correcto:

let x = 1;
++x;
    

Pero si por alguna razón olvidamos poner el primer punto y coma al minimizar obtenemos let x=1++x; que es un error de sintaxis. Por eso el minimizador avisa en ese caso que dos operadores "++" o "--" sólo pueden estar al inicio o final de una sentencia o expresión, pero no en medio.

Refactorizar JS y otras opciones

Usando la técnica de refactorizar nombres de las variables en JS para acortar el tamaño del código favoreceremos la transferencia de datos. En este campo pondremos en la configuración una clave cualquiera como "REFACTORIZAR" de tal forma que la anotaremos como comentario en cada función. Por ejemplo:

function fun(varA, varB){//<REFACTORIZAR>
    let varC = varA + varB;
    return varC;
}//</REFACTORIZAR>
    

obtendremos finalmente el siguiente código minimizado y refactorizado:

function fun(a,b){let c=a+b;return c}
    

Se aprecia que se puede conseguir un ahorro de espacio cuando tenemos muchas variables con nombres largos. Se trata de sustituir las variables por la serie de una o dos letras "a", "b", ..., "z", "aa", "ab", ..., "zz". De esta forma podemos reducir hasta 812 nombres de variables por función. Si hubiesen más será advertido como error y no se refactorizará el código.

Otra opción de la configuración del minimizador es eliminar trozos de HTML no publicable. En mis documentos en desarrollo sigo manteniendo el meta-elemento <meta name="keywords" content="..." />. Los buscadores ya no aconsejan incluirlos, pero en desarrollo lo sigo necesitando para crear un índice de palabras claves para el buscador interno de este sitio. Cuando minimizo los documentos esos elementos son eliminados, para lo cual incluyo la expresión regular <meta\s+name\s*=\s*"keywords"\s+content\s*=\s*"[^"]+"\s+/> en esa configuración del minimizador.