Retrasar la carga de Javascript con jQuery.getScript().
0. Índice de contenidos.
- 1. Introducción.
- 2. Entorno.
- 3. Una prueba de concepto.
- 4. jQuery.getScript().
- 5. Usando el API de bibliotecas AJAX de Google.
- 6. Referencias.
- 7. Conclusiones.
1. Introducción
Es habitual, si nuestro proyecto no está reñido con temas de accesibilidad, que si la vista está construida en base a (x)html, hagamos uso
de funciones propias o de librerías javascript, para imprimir dinamismo a nuestras páginas, manipular el árbol DOM (en el que se traduce el (x)html
en el navegador) en respuesta a eventos del usuario, modificar los estilos en el cliente, incluir componentes visuales «ricos»,…
Los scripts son descargados, parseados y ejecutados antes de que el navegador comienze la renderización de una página web. Aunque el script
esté incluido en un fichero externo que se almacene en caché, el procesamiento de su contenido se bloquea hasta que el navegador carga el código
del disco y lo ejecuta. Además, la mayoría de los navegadores, mientras procesan el javascript, bloquean el resto de descargas aunque se encuentren en ubicaciones
distintas.
El resultado es que el procesamiento de javascript en el cliente influye en el tiempo de carga de la página y, la mayoría de las veces, no se
requiere hacer uso de las funciones que incluye en la carga inicial. El recurso más usado es incluir las etiquetas de <script… en el pie del documento html, justo antes del body, con ello su carga no afecta a la
del resto de la página.
En este tutorial vamos a analizar cómo realizar dicha carga, una vez que la página ha sido renderizada, de una manera más elegante, con el soporte de
jQuery.
Haciendo uso de las recomendaciones de Google, que podemos comprobar a través de la herramienta
Page Speed, si tu script no
contiene más de 25 funciones, que no se usen en el onload de la página, no inviertas ningún esfuerzo en este sentido.
2. Entorno.
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil MacBook Pro 17′ (2.93 GHz Intel Core 2 Duo, 4GB DDR3 SDRAM).
- Sistema Operativo: Mac OS X Snow Leopard 10.6.1
- Mozilla Firefox 3.6.
- Firebug 1.5.2
- Page Speed 1.6
3. Una prueba de concepto.
Para comprobar que, efectivamente, se produce una mejora en el rendimiento, necesariamente tenemos que medir tiempos antes y después de la mejora.
Para ello hemos preparado una página que requiere de la descarga de un script cuya generación desde el servidor se retarda deliberadamente 3 segundos.
El código de la página test.jsp, que hace las veces de librería javascript, es el siguiente:
function log(msg){ alert(msg); }
Y el código de la página html este otro:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="/wp-content/uploads/tutorial-data/js/test.jsp"></script> <title>getScript()</title> </head> <body onload="log('Load was performed');"> <img src="/wp-content/uploads/tutorial-data/images/powered_by_autentia.jpg" /> <img src="/wp-content/uploads/tutorial-data/images/BanerLibro.jpg.jpg" /> <img src="/wp-content/uploads/tutorial-data/images/rueda.png" /> </body> </html>
Con la ayuda del visor de actividad de Page Speed
y limpiando la cache del navegador, tomamos los tiempos:
Lo interesante es ver la línea de carga del script y como se produce un bloqueo del resto de descargas hasta su finalización. Más interesante es ver
el punto en el que se produce el renderizado (Paint), en negro, puesto que no se produce hasta que el script no se descarga.
4. jQuery.getScript().
La idea es hacer uso de la función getScript() de jQuery que, a través de una petición Ajax, lleva a cabo la descarga del script en segundo plano sin afectar al
rendimiento. Lo más interesante es la posibilidad de declarar un método de callback que será invocado cuando se produzca la descarga total del script.
El código de la página quedaría como sigue:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script src="/wp-content/uploads/tutorial-data/http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function() { $.getScript('js/test.jsp', function() { log('Load was performed.'); }); }); </script> <title>getScript()</title> </head> <body> <img src="/wp-content/uploads/tutorial-data/images/powered_by_autentia.jpg" /> <img src="/wp-content/uploads/tutorial-data/images/BanerLibro.jpg.jpg" /> <img src="/wp-content/uploads/tutorial-data/images/rueda.png" /> </body> </html>
Y, tras limpiar la caché del navegador, si solicitamos la página de nuevo podemos observar que la secuencia de descarga es distinta:
El tiempo de carga es similar, si bien, mientras se produce la descarga del javascript el cliente ya está visualizando la página, ya se ha procedido
a su renderizado, la secuencia Paint (en negro) no espera.
Pero… ¿ahora lo que necesitamos es la descarga de la librería de jQuery?. Efectivamente y sí, en el siguiente punto vamos a ver, también,
como minimizar su espera.
5. Usando el API de bibliotecas AJAX de Google.
Para mejorar la carga estamos incluyendo la librería de javascript jQuery que requiere, a su vez, una descarga puesto que es en la que nos apoyamos.
Lo primero es que usaremos la versión comprimida, con lo que la descarga será de solo de unos pocos bytes y, lo segundo, es que intentaremos usar la
librería publicada en los servidores CDN de Google (Redes de distribución de contenidos), de modo que ahorramos ancho de banda y su carga es bastante
más rápida que desde nuestro propio servidor puesto que usamos un acceso global de gran velocidad.
En el API de bibliotecas AJAX de Google están publicadas las últimas
versiones de las librerías: jQUery, jQuery UI, Prototype, script.aculo.us, MooTools, Dojo, Yui de Yahoo, Ext Core,… y, además, se proporciona un
cargador de librerías propio, como el que estamos analizando en este tutorial, pero de Google (google.load();) que permite recibir como parámetro la
versión de las librerías que aloja que queremos cargar.
Haciendo uso o no del cargador de Google la idea es atractiva, sobre todo porque es el primer escalafón de servicios de
Google App Engine.
6. Referencias.
- http://code.google.com/intl/es-ES/speed/page-speed/docs/payload.html#DeferLoadingJS
- http://code.google.com/intl/es-ES/apis/ajaxlibs/
7. Conclusiones.
Espero que os haya resultado, al menos, interesante. Seguimos haciendo uso extensivo en nuestros desarrollos de jQuery, per se,
y con el soporte de RichFaces.
Os animamos también a que nos contéis vuestras experiencias.
Un saludo.
Jose