Wextensible

Las reglas de PageSpeed Insights (extensión y on-line)

Web PageSpeed Insights

El sitio de Google Developers Make the Web Faster contiene documentación y herramientas para optimizar la carga de nuestra web. Nos ofrece una herramienta on-line llamada PageSpeed Insights. Pero mientras desarrollamos nuestra página en un servidor local podemos irla mejorando con la misma herramienta pero en forma de una extensión PageSpeed para instalar en Chrome o Firefox, pues la anterior on-line no puede pasar el test a dominios localhost.

Actualmente en mi Chrome 36 tengo la versión 2.0.4.3 de la extensión PageSpeed. Pero hemos de tener en cuenta que la versión on-line es más completa que la extensión, aunque Google Developers asegura que irá actualizando la extensión para que realice lo mismo que la versión on-line. La versión on-line tiene una ventaja adicional pues hace pruebas independientes para móviles y ordenadores, con un test de usabilidad para móviles que tampoco tiene la extensión.

Aunque ambos PageSpeed no sean iguales, yo voy confeccionando la página y pasándole la extensión para ir corrigiendo cosas. Al finalizar la página, o bien antes de terminarla si tengo una duda con algo, subo la página al sitio en producción y le paso la versión on-line. En resumen, se trata de combinar ambas herramientas para ir solucionando todos los problemas que nos presente.

Reglas de velocidad de la extensión PageSpeed Insights

La extensión PageSpeed Insights dispone 27 reglas de optimización, que por orden alfabético son las siguientes (los vínculos llevan a apartados en este tema o el siguiente):

  1. Aplazar el análisis de JavaScript
  2. Combinar las imágenes en objetos móviles CSS
  3. Eliminar las cadenas de consulta de recursos estáticos
  4. Especificar caché de navegador
  5. Especificar dimensiones de la imagen
  6. Especificar un conjunto de caracteres al principio
  7. Especificar un validador de caché
  8. Especificar una cabecera "Vary" con el valor "Accept-Encoding"
  9. Evita los redireccionamientos a páginas de destino
  10. Evita un conjunto de caracteres en la metaetiqueta
  11. Evitar la directiva "@import" en CSS
  12. Evitar solicitudes incorrectas
  13. Habilitar Keep-Alive
  14. Habilitar compresión
  15. Insertar pequeños recursos CSS
  16. Insertar pequeños recursos JavaScript
  17. Introducir recursos CSS en el encabezado del documento
  18. Minificar CSS
  19. Minificar HTML
  20. Minificar JavaScript
  21. Minimizar el tamaño de la solicitud
  22. Minimizar redireccionamientos
  23. Ofrecer imágenes a escala
  24. Ofrecer recursos de una misma URL
  25. Optimizar el orden de los estilos y de las secuencias de comandos
  26. Optimizar imágenes
  27. Utilizar preferentemente recursos asíncronos

Esta lista la obtengo directamente desde la extensión. En la documentación de Google Developers están agrupadas de otra forma y complementadas con otros consejos de optimización. Es el tema de Web Performance Best Practices donde hay un montón de cosas que aprender.

Reglas de velocidad de PageSpeed Insights on-line

Las reglas de PageSpeed Insights en la versión on-line se exponen a continuación, donde las que contienen el vínculo no se encuentran en la extensión (los vínculos llevan a apartados en este tema o el siguiente):

  1. Evitar los redireccionamientos a páginas de destino
  2. Habilitar compresión
  3. Mejorar el tiempo de respuesta del servidor
  4. Especificar caché de navegador
  5. Minificar recursos
  6. Optimizar imágenes
  7. Optimizar la entrega de CSS
  8. Priorizar el contenido visible
  9. Quitar el JavaScript que bloquea la visualización de contenido
  10. Usar scripts asíncronos

Reglas de usabilidad de PageSpeed Insights on-line

La versión on-line tiene además unas reglas de usabilidad que no se encuentran en la extensión:

  1. Evitar los plugins
  2. Configurar ventana gráfica
  3. Adaptar el contenido a la ventana gráfica
  4. Aplicar el tamaño adecuado a los botones táctiles
  5. Utilizar tamaños de fuente que se puedan leer

Estas reglas puntúan aparte de las de velocidad (las anteriores) y aparecen en el test para móviles. En este tema no las incluyo pero también es convenientes revisarlas.

Acerca de estos temas

En estos dos temas presento las 27 reglas de la extensión y las 4 de la versión on-line en los siguiente grupos, divididos en dos temas para no alargar en exceso el contenido de la página.

Los vínculos resaltados con color de fondo azul claro son enlaces a temas de este sitio que ya he publicado anteriormente. El icono de PageSpeed () lleva a la documentación de Google Developers. El texto con fuente diferente y fondo beige es un resumen de información general extraído directamente de esa documentación de Google Developers. El resto del texto es que el que yo aporto, con el objeto de complementar o resumir la documentación de Google, pero no debe dejar de leerla porque es la base para entender todo esto.

Algunos apartados ya los he desarrollado en temas que he publicado en este sitio. En ese caso me limitaré a resumir un poco las acciones a llevar a cabo. Otros apartados són más extensos pues son contenidos que hasta ahora no había publicado.

Servidor

Hay varias cosas que podemos hacer desde el servidor para optimizar la velocidad de carga. Trabajar en este objetivo supone también el beneficio adicional de aliviar la carga del servidor. Acciones como el cacheado, evitar redirecciones o minimizar cabeceras harán que el servidor sea más eficiente gestionando un mayor número de peticiones.

Mejorar el tiempo de respuesta del servidor (on-line)

PageSpeed Docs: Tiempo respuesta servidor El tiempo de respuesta del servidor indica lo que tarda en cargar el código HTML necesario para mostrar la página desde el servidor, restando la latencia de red entre Google y el servidor. Puede haber diferencias entre una carga y otra, pero no deberían ser muy marcadas. De hecho, un tiempo de respuesta del servidor muy variable podría indicar un problema de rendimiento subyacente. Esta regla se activa cuando PageSpeed Insights detecta que el tiempo de respuesta del servidor es superior a 200 ms.

Time To First Byte en WebPageTest.org

El tiempo de respuesta del servidor es el que éste se toma para conformar la respuesta. Hasta el momento pocas veces he obtenido un mensaje de esta clase. La documentación habla de medir ese tiempo de respuesta. Pero si estamos en un alojamiento compartido hemos de usar herramientas externas para eso. Por ejemplo la herramienta WebPageTest nos mide el TTFB o Time To First Byte, tiempo hasta el primer byte, diciendo que el TTFB es el tiempo que transcurre desde que se solicitó la página hasta el momento en el que llega el primer byte al navegador. Una parte parte de este tiempo es la que invierte el servidor construyendo la página para el usuario.

De vez en cuando consulto la página principal en esa herramienta. Puede ver un PDF con un informe de Wextensible.com que acabo de realizar. Hay un cuadro inferior con el desglose de tiempos que han tomado todos los recursos. La captura de pantalla junto a estos párrafos es parte de ese informe y muestra tiempos entre 135 ms y 161 ms.

En la imagen puede ver la petición del HTML, que consta de un DNS Lookup (120 ms) y una conexión inicial (131 ms), tras lo cual el navegador envía la petición. Entonces el navegador queda a la espera de recibir el primer byte, el cual llega tras una espera de 158 ms. Pero de ese tiempo hay que restar la latencia de la red, que en ese caso podría estar en torno a los 130 ms igual que la conexión inicial, pues ésta consumirá un RTT completo (ver más sobre esto en el tema latencia web). Por lo tanto el servidor sólo paso 158-130 = 28 ms conformando la respuesta.

Pagespeed también resta la latencia al TTFB para obtener el tiempo en el servidor. Éste no puede estar mucho más tiempo sirviendo un simple HTML, a no ser que esté momentáneamente colapsado atendiendo a muchas peticiones o bien la respuesta necesite consultar bases de datos y otras operaciones más complejas. PageSpeed nos permite hasta 200 ms en esas tareas en el servidor.

Habilitar Keep-Alive

PageSpeed Docs: keep-alive El host XXX, que proporciona servicio a los recursos que se indican a continuación, debe habilitar Keep-Alive

La extensión PageSpeed da un mensaje como el anterior, pero no ofrece mas información ni un enlace a la documentación de Google Developers. No he podido encontrar ninguna información en esa documentación. En el icono adjunto he puesto un enlace a stackoverflow.com de una consulta acerca de esto.

En este sitio ya he publicado algo sobre la necesidad de tener activado keep-alive en el servidor. Llegará al navegador con un par de cabeceras, una es Connection: Keep-Alive y la otra será algo como Keep-Alive: timeout=2, max=200. Esta última quiere decir que el servidor mantendrá abierta la conexión durante 2 s (timeout) para un máximo de 200 peticiones (max-requests). El beneficio de Keep-Alive se observa con una herramienta con la que podemos llevar a cabo un test de la conexión web. Tras la el inicio de petición que tiene el coste del DNSLookup y la conexión inicial, el resto de recursos pueden recuperarse reaprovechando esa misma conexión dentro de la ventana del Timeout.

Y esto es algo que hacen usualmente los navegadores. Establecen hasta 6 conexiones en paralelo y traen varios recursos en cada conexión, lo que tiene su mayor ventaja cuando el servidor mantiene la conexión abierta durante un cierto tiempo. Aunque también habría que observar que mantener conexiones abiertas y ociosas supone mermar recursos al servidor. Es posible que muchos sitios desactiven el Keep-Alive si tienen un abultado tráfico de peticiones.

Evita los redireccionamientos a páginas de destino

PageSpeed Docs: redirecciones Esta regla se activa cuando PageSpeed Insights detecta que tienes más de un redireccionamiento desde una URL a una página de destino. Dado que los redireccionamientos desencadenan un ciclo de solicitudes y respuestas HTTP adicional y aumentan la latencia, es importante reducir al mínimo el número de redireccionamientos enviados por la aplicación. Evita los redireccionamientos HTTP para reducir el tiempo de carga de una página. Te recomendamos que revises bien el diseño de tu sitio para ver en qué secciones puedes mejorar el rendimiento.

Minimizar redireccionamientos

PageSpeed Docs: evitar redirecciones Minimizar los redireccionamientos HTTP de una URL a otra reduce los tiempos de retorno adicionales y el tiempo de espera para los usuarios.

Evitar redirecciones 301

Estas dos últimas reglas son aparentemente iguales. Al menos yo no he podido encontrar diferencias significativas. En cuanto a las redirecciones es evidente que a veces son necesarias, pero en todo caso hay que hacerlas desde el servidor. En este sitio puede ver el tema sobre redirecciones 301 en el servidor Apache. En la imagen adjunta puede ver una captura de una redirección de una página de este sitio. Dado que la cambié de sitio y la renombré, tuve que poner una redirección en un htaccess. Vea como el servidor responde con un 301 devolviéndole también la ruta correcta. El navegador pide la página con esa nueva URL. Pero la redirección nos ha costado 248 ms. Es obvio y poco más hay que decir: evitar las redirecciones siempre que se pueda.

Minimizar el tamaño de la solicitud

PageSpeed Docs: tamaño petición Mantener cookies y cabeceras de solicitudes del menor tamaño posible garantiza que una solicitud HTTP se pueda incluir en un único paquete.

Si tenemos una página que usa sesiones con cookies, el navegador enviará las cookies con todas las peticiones de esa página y de otras páginas mientras la sesión siga abierta y no se hayan borrado las cookies. Las cookies ocuparán espacio tanto con la petición al servidor como al volver desde el servidor con cualquier recurso, aunque éste no necesite esas cookies para nada (p.e., las imágenes). Si ya no se necesitan debemos borrarlas.

El borrado de las cookies que ya no se usan lo hago en el script prehjc.php con este código:

<?php
    if ($extension == "html"){
        $cks = array("contacto", "buscador");
        foreach($cks as $val){
            if (isset($_COOKIE[$val])) setcookie($val, '', 1, '/');
        
    ...
?>

Por ahora en este sitio uso sesiones en las páginas PHP (con extensión .php) del Buscador y Contacto. Las cookies se llaman igual. Estos documentos no se cachean en ningún caso. El resto de páginas no usan sesiones y su extensión es .html, de tal forma que cada vez que se solicita un documento de éstos y si la petición viene con cookies se envía una cookie de borrado con la función de PHP setCookie($val, '', 1, '/') con esos argumentos.

El script de pre-ejecución prehjc sirve de pre-procesamiento de varias tareas. Inicialmente lo creé para comprimir web con PHP. Luego me ha servido para otros usos como implementar caché web con PHP, priorizar CSS above-the-fold con PHP y por último para implementar un control de versiones con revalidación desde caché. Referencias a este script aparecerán por tanto en varios sitios en estos temas.

Ofrecer recursos de una misma URL

PageSpeed Docs: URL's coherentes Es importante mostrar un recurso de una URL única para eliminar bytes descargados duplicados y tiempos de retorno adicionales.

Poco hay que de decir acerca de esto. En mi caso construyo las URL's de forma relativa en los elementos de la página. Y si tengo una imagen vinculada desde varios documentos, utilizo la misma imagen e igual URL, porque si el navegador ya la cacheó en una visita a una de las páginas, ya estará disponible en caché cuando se visite la otra.

Es conveniente tener un esquema inicial de la estructura de carpetas del sitio en el servidor con objeto de referenciar los documentos con cierta coherencia. Y también es aconsejable tomar la decisión de usar solo rutas absolutas o relativas, pero no mezclar ambas formas.

Comprimir recursos

Cabeceras de recurso comprimido con Gzip

Uno de los mayores problemas que nos encontramos para disminuir los tiempos de carga de las páginas web tiene que ver con el tamaño de los recursos. Puesto que estos datos deben viajar por la red, cuanto menor sea su volumen tanto más rápido los tendremos disponibles en el navegador. Una forma de reducir ese volumen es comprimiendo los recursos antes de ser enviados por el servidor. Vea el tema comprimir web para implementarlo.

Habilitar compresión

PageSpeed Docs: comprimir gzip Comprimir recursos con gzip o con deflate puede reducir el número de bytes enviados a través de la red.

En el enlace anterior podrá encontrar más información. Podemos comprimir usando un htaccess de Apache. Con algo tan sencillo como AddOutputFilter DEFLATE .js .css .html enviaríamos esos documentos comprimidos. Pero al aplicarlo en mi servidor de alojamiento compartido en 1and1 me econtré con que no funcionaba. Tras intentarlo con el servicio técnico desistí y pasé a comprimir con PHP los documentos usando php_flag zlib.output_compression On en un archivo php.ini. Había que manejar como PHP las salidas de documentos HTML, JS y CSS. Fue cuando empecé a usar el script de pre-ejecución prehjc.php para complementar el envío de cabeceras Content-Type para los CSS y JS.

Especificar una cabecera "Vary" con el valor "Accept-Encoding"

PageSpeed Docs: caché web Indica a los servidores proxy que almacenen en caché dos versiones del recurso: una comprimida y otra sin comprimir. Esto permite evitar que se produzcan incidencias relacionadas con proxies públicos que no detectan la presencia de una cabecera Content-Encoding de forma adecuada.

Poco puedo añadir a lo comentado en la documentación de Google Developers. Simplemente seguir este consejo y enviar con PHP una cabecera header("Vary: Accept-Encoding"), incluso en las respuestas 304.

Cachear recursos

Caché web con Cache-Control y Last-Modified

La caché web almacena copias de los recursos de una página web en el navegador o en servidores proxy con objeto de evitar las limitaciones de la latencia y el ancho de banda. En ese primer enlace podrá encontrar información acerca de implementar una caché web. Aquí también uso el script prehjc.php debido a que los documentos HTML, CSS y JS son manejados con PHP para enviar cabeceras Content-Type necesarias para la compresión Gzip (para CSS y JS). Por lo tanto una vez que salen manejados por PHP ya no podemos enviar cabeceras de caché con Apache y hemos de servir esas cabeceras con PHP.

Especificar caché de navegador

PageSpeed Docs: especificar caducidad en caché web Establecer una fecha de caducidad o una edad máxima en las cabeceras HTTP de los recursos estáticos indica al navegador que cargue los recursos descargados previamente del disco local en lugar de hacerlo a través de la red.

Podemos configurar el servidor para que envíe una cabecera con una fecha de caducidad como Expires: Sun, 15 May 2014 21:15:42 GMT. O también usar la alternativa de HTTP 1.1 con Cache-Control:max-age=86400, enviándose la cabecera con la duración de vida en segundos del recurso en caché. Son dos alternativas de las que debemos elegir una.

Especificar un validador de caché

PageSpeed Docs: validador de caché Al especificar un validador de caché (por ejemplo, una cabecera Last-Modified o ETag), se asegura de que se pueda determinar de forma eficaz la validez de los recursos almacenados en caché.

No basta con enviar la fecha de caducidad o la duración de vida del recurso. Además hay que enviar una cabecera Last-Modified o, alternativamente E-Tag. Sin esto el navegador no puede saber cuando se modificó el recurso por última vez y no se beneficiará de las consultas 304 enviando una cabecera If-Modified-Since o If-None-Match respectivamente para las alternativas anteriores.

Eliminar las cadenas de consulta de recursos estáticos

PageSpeed Docs: cadenas consulta Habilitar el almacenamiento en caché público en las cabeceras HTTP de los recursos estáticos permite que el navegador descargue recursos de un servidor proxy cercano en lugar de hacerlo a partir de un servidor de origen remoto.

Algunos proxies no cachean recursos con cadenas de consultas (URL's con "?"). Si la información desde el servidor se está enviando de esa forma, es posible que el proxy se niegue a cachear los recursos, lo que debemos tener en cuenta. Siempre es preferible propagar el SID en sesiones PHP con con sólo cookies tal como recomiendan para mayor seguridad, por lo que ese problema no me afecta.

La regla 21 sobre minimizar el tamaño de la solicitud también habla acerca de las cookies.

Minimizar recursos

Minimización de recursos

Con la minimización de recursos 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. Minimizar, minificar o compactar son términos que definen lo mismo: quitar todo lo que un documento no necesita para ser renderizado por un navegador.

Tipo% Reducción
HTML16,0 %
PHP32,1 %
CSS59,2 %
JS51,8 %
Totales19,4 %

No debemos desestimar el ahorro en bytes que se consigue minimizando los documentos. Cuando minimicé los 185 documentos que por aquel entonces tenía en mi sitio, conseguí una reducción promedio de 19,4%. Los CSS y JS son los que más se benefician de esta reducción. Actualmente el archivo general.js que se descarga con todas las páginas y que contiene el JS general para el sitio ocupa unos 119 KB en bruto. Tras la minimización se reduce hasta 47 KB (reducción de 60,5%). Después de esto al navegador llega comprimido con un tamaño de 13,9 KB (reducción de 70,4%). Por lo tanto la reducción por minimización se acerca mucho a la de la compresión. Con respecto al primer tamaño suponen una reducción de 88,3%.

Hay que recordar que el control de congestión de las conexiones TCP puede tener una ventana inicial (IW) de 14600 Bytes. Todo recurso que ocupe más de este tamaño necesitará de uno más RTT adicionales. Por lo tanto hay que mantener el tamaño final de los recursos, especialmente los JS y CSS, por debajo de ese valor, no olvidando que hay que dejar algunos cientos de bytes para las cabeceras HTTP. En resumen, que no pase por ejemplo de 14000 Bytes. Si son HTML hemos de asegurarnos que con los primeros 14000 Bytes del documento podamos renderizar la parte superior de la página.

Me he construido una propia herramienta para minimizar los documentos. PageSpeed también nos ofrece el documento minimizado. O bien en Internet podrá encontrar más herramientas para esto. Y poco más hay que decir de las tres reglas siguientes. PageSpeed las separa por tipo de documento.

Minificar HTML

PageSpeed Docs: minimizar HTML Compactar el código HTML, incluido cualquier código CSS y JavaScript en línea que contenga, puede ahorrar una gran cantidad de bytes de datos y acelerar el tiempo de descarga, análisis y ejecución.

Minificar CSS

PageSpeed Docs: minimizar CSS Compactar el código CSS puede ahorrar una gran cantidad de bytes de datos y acelerar el tiempo de descarga, análisis y ejecución.

Minificar JS

PageSpeed Docs: minimizar JS Compactar el código JavaScript puede ahorrar una gran cantidad de bytes de datos y acelerar el tiempo de descarga, análisis y ejecución.