Minimización y código fuente de los documentos
Introducción: Optimizando la carga de los recursos
Desde que empecé con esto del Desarrollo Web me propuse ir montando un sitio de forma gradual. Cada vez que hago un cambio importante en este sitio wextensible.com guardo en un histórico toda la estructura de carpetas y archivos antes de incorporar la nueva modificación. En localhost he creado dominios virtuales para cada uno de esos momentos, capturando la página de inicio en la serie de imágenes que se presentan al lado de este texto. La primera es del 16 de Mayo de 2010, cuando subí por primera vez este sitio. La última es del pasado 8 de Julio de 2012. He seleccionado sólo aquellas que suponen un cambio importante en la estructura de la página, de tal forma que esa modificación afectó a la carga de los recursos.
El tiempo de carga de los recursos es el que invierte un navegador desde el momento en que se solicita una página hasta que está completamente cargada. Hay muchas formas de llevar un seguimiento de esto. Podemos usar Webmasters de Google que nos da una gráfica como la de este sitio wextensible.com. No podemos ejecutar el test a voluntad, pues el último es de hace más de un mes (9 de Junio). De todas formas se observa como ha ido incrementándose el tiempo de carga medio del sitio en el último año.
También podemos usar otras herramientas como Pingdom Tools donde se puede testear libremente una página. Este es el resultado del test de este sitio ejecutado hoy 14 de Julio de 2012. He recortado esa imagen pero también ofrece mucha más información, como gráficas, histórico de tests, análisis de los recursos de la página, recomendaciones para optimizar la carga, etc.
Pero las herramientas que creo que son indispensables para tratar de entender y mejorar esto de la carga de recursos son las que podemos encontrar o agregar al propio navegador. Los navegadores importantes tienen estas Developer Tools o Herramientas de Desarrollo. En este tema usaré las de Chrome. Por un lado tenemos Network que nos da el timeline o línea de tiempos de carga de los recursos. Por ejemplo, esta imagen es de la página de inicio del histórico de este sitio el 16 de Mayo de 2010. Podemos analizar el orden de carga, los tiempos y comprobar cuando está el DOM cargado (línea azul vertical) así como cuando se carga toda la página (línea roja vertical). Permite vaciar la caché de esa página para analizar los tiempos sin caché, que en definitiva son esos sobre los que tenemos que trabajar. Hay que evitar a toda costa una primera impresión negativa sobre los tiempos de carga en el caso del usuario que nos visita por primera vez y por tanto no tiene nada en caché.
Chrome también dispone de Audits que realiza un análisis y nos dice donde podemos optimizar los recursos para que la página se cargue más rápido. Pero la mejor opción es instalar PageSpeed en Chrome o Firefox. Más que de análisis se trata de una herramienta que recomienda una serie de puntos para optimizar la carga de los recursos. Hay una documentación centralizada en Make the Web Faster de Google. Ahí podemos encontrar información de Web Performance Best Practices que aclara por dónde tenemos que atacar este tema de optimizar la carga de recursos.
Por supuesto, son muchos aspectos que hay que tocar. Y yo estoy empezando a estudiarlos. Por ejemplo, esta es una imagen de esa herramienta PageSpeed sobre la página del histórico del 24 de Mayo de 2012. Se observa una puntuación de 44%. Hay muchas cosas por hacer y, sobre todo, por entender cuál es exactamente el problema. Sin seguir el orden de prioridad he decidido empezar por analizar el tamaño de los recursos y tratar de minimizar (o minificar) los documentos.
Tamaño y peticiones
La herramienta Networks de Developer Tools de Chrome me ha servido para recopilar los valores del tamaño de los recursos y número de peticiones de una página. En este caso he analizado todas las versiones de la página de inicio de este sitio wextensible.com, desde la primera publicada en Mayo 2010 hasta la más reciente del 8 de Julio de 2012. Las gráficas junto a este texto exponen todo esto. En la primera se observa como evoluciona el tamaño total de los recursos de la página. A partir de Noviembre de 2011 decido incorporar más imágenes con el texto. Indudablemente un texto soportado con imágenes resulta más atractivo. Pero el tamaño de los recursos crece desproporcionadamente. Vemos que la gráfica sigue creciendo hasta que con la última publicación del 8 de Julio se produce un signficativo descenso. Es en ese momento cuando minimizo (o minifico) los documentos HTML, JS y CSS.
En la segunda gráfica puede ver la evolución histórica del tamaño agrupado por tipos de recursos de la página de inicio. Se observa que la minimización de documentos es más importante en los JS y en menor medida en los CSS y HTML. Las imágenes (tipo IMG) con extensiones jpg, png o gif son realmente recursos ya comprimidos, por lo que no se les aplica ninguna acción. Comprimir una imagen ya comprimida puede incluso incrementar su tamaño. En un futuro tendré que buscar la forma de optimizar el tamaño de las imágenes. Cosas como el diseño adaptativo (responsive design) para las imágenes son objetivos que debería implementar en este sitio.
Pero el coste de la carga de los recursos no sólo está afectado por el tamaño de los mismos. Además también repercute el número de peticiones. Cuando el número de peticiones es muy alto en comparación con el tamaño de los recursos se produce un incremento del tiempo de carga importante. El navegador puede ejecutar las peticiones de forma concurrente, pero supone de todas formas que por cada recurso el navegador debe realizar una petición al servidor, incluso para una pequeña imagen de un centenar de bytes. Aquí entraría en juego usar sprites para combinar varias imágenes de relativo pequeño tamaño en una matriz de imágenes y descargarlas todas de una sola vez. Se aplicarían a imágenes que no se espera que cambien con frecuencia. Pero este tema lo tocaré en otra ocasión.
En la tercera gráfica puede observar la evolución del número de peticiones. La última modificación con los documentos minimizados redujo el tamaño total, aunque por supuesto no así el número de peticiones. No sabría decir exactamente en que medida afectan el tamaño y el número de peticiones en la carga. Digamos que el tiempo de carga podría ser proporcional a ambos factores. Para tratar de unificarlos en una sóla gráfica tomaremos el producto Tamaño × Peticiones. De esta forma la cuarta gráfica nos muestra este factor TxP para los distintos tipos de recursos. En la última gráfica vemos este factor para los recursos sin incluir las imágenes (en rojo) y para el total (en azul). Es evidente que tras minimizar los documentos el siguiente paso sería reducir los tiempos de carga de las imágenes, reduciendo el número de peticiones y optimizando los tamaños.
Minimizar o minificar documentos
Con la actualización del 8 de Julio de 2012 he modificado todo el sitio para minimizar los documentos (o minificar como dicen algunos). Con la minimización de documentos tratamos de reducir los espacios y eliminar comentarios en los documentos HTML, PHP, JS y CSS para que ocupen el menor tamaño posible. Así se consigue una velocidad de transferencia superior y por tanto una mayor rapidez en la carga de la página. Esto es especialmente importante cuando tenemos nuestro sitio en un alojamiento compartido. Pero también la tendencia actual es incorporar más JavaScript a las páginas, en gran medida proveniente de fuentes externas, como los botones me gusta de la redes sociales por ejemplo. Todo esto entorpece la carga de la página por lo que hemos de reducir tiempos de carga atacando todas las vías posibles. Y esta de la minimización de documentos es una de ellas.
Es obvio que en un sitio con un objetivo no orientado al desarrollo web habría que evitar la exposición de información sobre como está construida esa web. Pero ofrecer el código fuente de origen de los documentos de forma clara y comentada es un compromiso de este sitio, pues el objetivo es que todo el que lo desee vea exactamente cómo se hizo cada documento. Esto supone asumir un riesgo de seguridad, especialmente cuando expongo incluso el código PHP y lo que puede haber en las carpetas no públicas. Frente a ese riesgo lo único que puedo hacer es considerar las cuestiones de seguridad antes de agregar un nuevo componente.
El problema que existe al minimizar los documentos es que el usuario no podrá leer (y entender) el código fuente con la utilidades del navegador. Al menos a mí me resulta imposible incluso para el código minimizado que yo mismo he escrito. Podemos aún ver el código usando el árbol DOM en las herramientas de desarrollo del navegador. Pero ése es el que resulta tras la carga de la página, no teniendo porque ser tal y como salió del servidor (por ejemplo, JavaScript puede modificar HTML en la carga de la página). Además en ningún caso el navegador ofrece código PHP para páginas que combinan HTML y PHP, es decir, el código de origen almacenado en el servidor antes de que sea servido. Para conseguir ambos propósitos, minimizar y ofrecer código fuente de origen, agrego un nuevo botón Código en la barra superior de los documentos. Lleva a una página con el código resaltado que obtengo con una de las últimas herramientas, el resaltador de código que, precisamente, también funcionan dentro del marco de herramientas web que publiqué el 8 de Julio de 2012. En ese marco se puede instalar también un minimizador de documentos, herramienta con la que he llevado a cabo la minimización de este sitio.
Minimizando documentos con PageSpeed o con una herramienta propia
Hay muchas herramientas para minimizar o minificar documentos. Mi primer intento fue usar PageSpeed para este cometido. En sus recomendaciones nos da incluso el recurso minimizado. Pero finalmente construí mi propio minimizador de documentos. Para ver el motivo de esto analizaremos un página de prueba. Contiene diferentes casos para forzar la herramienta minimizadora. Por un lado la de PageSpeed ofrece el código minimizado tal como muestra esta captura de pantalla. Las diferencias entre minimizar con mi herramienta y PageSpeed son las siguientes:
Característica | PageSpeed | Minimizador |
---|---|---|
Minimizar página de prueba con un tamaño de 28.9 KB | Resultado | Resultado |
Tamaño final | 23.9 KB | 24.8 KB |
Reducción | 17.3 % | 14.2 % |
Minimiza contenido script o css interno | Sí | Sí |
Elimina saltos de línea innecesarios | No (\r\n seconvierte en \n ) | Sí |
Preserva comentarios HTML condicionales | Sí | Sí |
Preserva espacios en <pre> y <textarea> | Sí | Sí |
Preserva espacios en estilos como white-space | No | Sí |
Consulta ese estilo en archivos CSS externos | No | Sí |
Puede declararse una lista previa de elementos, estilos o clases para filtrar lo que se minimiza | No | Sí |
Preserva espacios en elementos con atributos o clases a especificar en la herramienta | No | Sí |
Minimiza espacios entre atributos | Sí | Sí |
Elimina comillas de valores de atributos que no sean necesarias | Sí | No |
Elimina atributos por defecto como type="text" de loselementos <input> | Sí | No |
Elimina espacios entre elementos de bloques | No (deja los \n ) | Sí |
PageSpeed consigue más reducción que mi herramienta. Pero no preserva los elementos con estilo como white-space:pre
. Estos se comportan como elementos <pre>
y a efectos de presentar código fuente en una página es importante preservar el contenido de esos elementos. En mi herramienta además se pueden declarar lista de elementos, atributos, estilos o clases sobre los que no se minimizará el contenido. En los estilos y clases consulta el estilo en línea, el existente en el elemento <style>
y también el estilo externo vinculado en los elementos <link rel="stylesheet"...>
. En esta página de prueba hay muchos ejemplos que usan estas particularidades y por eso el resultado minimizado es de mayor tamaño que el de PageSpeed, entre otras razones que se exponen a continuación.
Otra diferencia importante es que PageSpeed deja todos los saltos de línea. En mi caso que trabajo en Windows, convierte los \r\n
en \n
. Yo los elimino o los convierto en un espacio simple, según sea el caso. Después de todo el renderizado HTML hará finalmente eso, a no ser que estén dentro de un elemento donde haya de preservarse el contenido como los <pre>
, <textarea>
o estilos white-space
.
Otro aspecto donde PageSpeed logra reducir tamaño es eliminando las comillas en los valores de atributos donde no se necesiten. Podría aplicar este principio a mi herramienta, pero aún tengo que estar seguro en que casos pueden eliminarse. Pueden ocurrir errores muy graves si esto no se hace adecuadamente. Además de implementarlo tendría que buscar la forma de corroborar que el resultado no ha sido alterado.
En cuanto a los atributos por defecto como eliminar type="text"
en los elementos <input>
, por ahora no lo voy a implementar. Sencillamente porque aún no tengo una lista de todos los casos donde podría omitirlos. Y no sólo tener esa lista, además quisiera saber exactamente que es lo que estoy omitiendo. Ésta y la anterior son mejoras a considerar.
En todo caso consigo una reducción importante como se observan en las gráficas del apartado anterior para la página de inicio. En la actualización de este sitio el día 8 de Julio de 2012 he publicado los 185 documentos ya existentes pero minimizados. En total habían unos 1203 documentos, contando también las imágenes y otros archivos así como los documentos HTML, PHP, JS y CSS de los ejemplos. Estos sin embargo no los minimicé pues al fin y al cabo son documentos de ejemplo que ponen en práctica un concepto teórico. Creo que deben conservar su estructura y además no suelen ser de gran tamaño. El resultado de la publicación por tipos de documento es el siguiente:
Tipo | Total minimizados | Total no minimizados | Sumas |
---|---|---|---|
HTML | 127 | 217 | 344 |
PHP | 12 | 65 | 77 |
CSS | 17 | 48 | 65 |
JS | 29 | 28 | 57 |
Imagen | 0 | 540 | 540 |
Otros | 0 | 120 | 120 |
Totales | 185 | 1.018 | 1.203 |
El resultado de la minimización global efectuada en esos 185 documentos es el siguiente:
Tipo | Documentos | Tamaño original KB | Tamaño minimizado KB | Reducción KB | Porcentaje |
---|---|---|---|---|---|
HTML | 127 | 5.072,91 | 4.261,47 | 811,44 | 16,0 % |
PHP | 12 | 209,08 | 141,94 | 67,14 | 32,1 % |
CSS | 17 | 46,77 | 19,10 | 27,67 | 59,2 % |
JS | 29 | 397,22 | 191,83 | 205,89 | 51,8 % |
Totales | 185 | 5.726,48 | 4.614,34 | 1.112,14 | 19,4 % |
Una ventaja de mi herramienta es que puedo minimizar también documentos PHP, es decir, minimizar todo el contenido de los documentos de origen. Aunque los PHP no se envían literalmente al navegador, cuánto menos ocupen más fácil le será al servidor manejarlos. Pero además esta herramienta para minimizar la tengo integrada en el marco de herramientas con otra para resaltar código, de tal forma que puedo publicar un documento minimizado y además ofrecer un mecanismo para ofrecer el código de origen de ese documento. Incluso los PHP. Las páginas de este sitio ya incorporan ese código resaltado con el botón Código ubicado en la barra de botones de la cabecera. En resumen, sea con la herramienta que sea hay que minimizar los documentos con el objeto de reducir los tiempos de carga.