Cargar jQuery desde un CDN o desde servidor

29 Jun 2011

Introducción

Esta es una pregunta que surge a menudo cuando se inicia un proyecto; a la hora de incluir la biblioteca jQuery (o alguna otra conocida), ¿es mejor hacerlo desde un CDN o desde nuestro propio servidor?

Para contestarla, en este artículo expondré cuáles son las ventajas que promete un CDN frente al servidor tradicional para pasar a valorarlas individualmente en su justa medida.

Finalmente, para no comprometer el funcionamiento de nuestra aplicación en aquellos casos en los que el servicio esté inactivo, propondremos una fórmula que actúe como respaldo de éste siguiendo una línea de desarrollo responsable.

OK pero, ¿qué es exactamente un CDN?

Un CDN, Content Delivery Network o Red de entrega de contenidos, es un sistema de computadoras que contienen copias de datos, colocados en varios puntos de una red con el fin de maximizar el ancho de banda para el acceso a los datos de clientes a través de la red. Un cliente tiene acceso a una copia de los datos cerca del cliente, en contraposición a todos los clientes que acceden al mismo servidor central, a fin de evitar cuellos de botella cerca de ese servidor.

Es decir, que cuando queremos incluir una biblioteca como jQuery en nuestra aplicación, el cliente la descargará desde un tercero en lugar de desde nuestro servidor.

Cuando hablamos de jQuery, los CDNs más recomendables son los ofrecidos por Google, Microsoft y la propia jQuery:

// From Google API
http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js
 
// From Microsoft
http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.1.min.js
 
// From jQuery
http://code.jquery.com/jquery-1.6.1.min.js // Minified version
http://code.jquery.com/jquery-1.6.1.js // Source version

¿Y qué ventajas tiene esto del CDN?

Básicamente, al utilizar un CDN en lugar de una copia local de nuestra biblioteca, obtendríamos tres ventajas iniciales:

  • Mayor velocidad en la descarga del recurso.
  • Ahorro de ancho de banda propio.
  • Uso más efectivo de la caché en el lado cliente.

Veamos cada uno de estos puntos de forma individual para analizar cómo afectarían a nuestra aplicación en el Mundo Real.

Velocidad de descarga: En este aspecto, hay que considerar que un servidor de terceros, como por ejemplo Google, tiene una mayor tasa de transferencia potencial que nuestro servicio de hosting (o servidor) habitual. Eso, hasta cierto punto, puede ser verdad, pero cuando hablamos de bibliotecas cuyo peso no sobrepasan los 500Kbs, la diferencia puede llegar a ser meramente testimonial.

Además de esto, también existe el factor regional: sobre el papel, si nuestro servidor está por ejemplo en China, cuando un usuario español realiza una petición, los datos tienen que viajar atravesando continentes; si en lugar de a China, el recurso solicitado se encuentra repartido en una red CDN, es presumible que la petición se realizará al nodo más próximo y, por tanto, los datos viajarán menos y llegarán antes. De nuevo, este factor es más teórico que práctico ya que a día de hoy, la diferencia entre ambos casos no es importante con paquetes de unos pocos Kbs.

Finalmente, en cuanto a la velocidad de descarga podríamos hablar de un tercer condicional: las peticiones simultáneas que pueden realizarse a un mismo servidor suelen limitarse en número (por lo general a un par de ellas), por lo que si nuestra aplicación está compuesta por muchos archivos, utilizar una segunda fuente permite que los archivos puedan descargarse de forma paralela disminuyéndose así el tiempo necesario.

Ahorro en cuanto a ancho de banda. No cabe duda de que si en lugar de ser nuestro servidor el que sirve un archivo, lo hace un tercero, estamos ahorrando el ancho de banda correspondiente. Sin embargo, de nuevo hay que tener en cuenta que estamos hablando de unas pocos Kbs por petición lo que, siempre que no tratemos de un site con varios cientos de miles de visitas mensuales, el coste es marginal. A día de hoy, los servicios de hosting poseen cuotas de transferencia mensuales que suelen ir de mucho a ilimitada. No obstante, si tenemos frecuentes problemas con este aspecto, el uso del CDN puede estar bien justificado.

Uso de la caché cliente. Aquí está la clave y la verdadera justificación al uso de un CDN. Cuando navegamos por la red, cada vez que entramos en una página, el navegador descarga todos los archivos dependientes: hojas de estilo CSS, Javascript, etc. y los guarda en memoria para recurrir a ellos en futuras visitas. Esto quiere decir que, a lo largo del día, nuestro navegador se llena de versiones de jQuery, cada una correspondiente a aquellas páginas (sites) por las que vamos pasando. Esto es así porque, cada vez que la petición se realiza a un servidor nuevo, el navegador entiende que se trata de un archivo distinto aunque tenga el mismo nombre y peso que otro ya almacenado. Esto resulta lógico: pensemos cuántas páginas tienen un fichero style.css, o un init.js por ejemplo; puede darse la circunstancia de que dos o varios de ellos tengan incluso el mismo tamaño aún siendo completamente diferentes. Frente a esa posibilidad, el navegador opta por descargarlo y guardarlo. Esto mismo ocurre con jQuery. Sin embargo, cuando usamos un CDN, los servicios que sirven la biblioteca son limitados: puede ser Google, Microsoft, Amazon, etc… y esto quiere decir que podemos aprovechar la versión cacheada que haya generado alguna otra página por la que hayamos navegado sin tener que volver a descargarlo.

El concepto es sencillo: un usuario ha navegado por tres sitios que requieren jQuery: dos de ellos lo cargan de forma local y el tercero lo hace desde el CDN de Google. Tras la sesión de navegación, el usuario tiene 3 copias locales de la biblioteca, dos de servidores diferentes y una proveniente de Google. Si el usuario visita ahora nuestra página y ésta también sirve jQuery desde Google, el navegador detecta que la referencia ya ha sido cacheada, omite la petición y tira de la versión guardada. Esto si supone una ventaja importante en cuanto a rendimiento en el lado cliente: todo lo que sea ahorrar peticiones supone mejores tiempos de carga para el usuario.

Ok, pero y si el CDN se cae o no está disponible?

Como comentamos al principio, no podemos comprometer el funcionamiento de nuestra aplicación a un tercero. Un desarrollo responsable implica que contemos con alguna medida que nos permita detectar si el CDN ha servido nuestro script para, en caso contrario, poder actuar.

La idea es realizar siempre la petición al CDN y comprobar inmediatamente si el servicio responde. Si no hay problemas continuamos pero en caso negativo, incluimos una copia local de nuestra biblioteca para continuar ofreciendo la funcionalidad necesaria.

La forma habitual de hacer esto es la siguiente:

<!-- Grab Google CDNs jQuery; fall back to local if necessary -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script>window.jQuery || document.write(unescape('%3Cscript src="/js_folder/jquery-1.6.1.min.js"%3E%3C/script%3E'))</script>

El código es sencillo: llamamos al CDN y comprobamos inmediatamente si existe el objeto jQuery mediante un condicional booleano. Si el primer término es false (lo que indicaría que el CDN no ha servido la biblioteca), incluimos directamente una nueva etiqueta script apuntando a nuestra copia local. Con esto, aseguramos que siempre se dispondrá del archivo dando preferencia al servido por el CDN frente al local.

Conclusión

Si bien el uso de un CDN tiene una serie de ventajas sobre el papel, para la gran mayoría de proyectos la única realmente relevante es la de reutilizar la caché generada en lugar de volver a descargar una copia local de la misma biblioteca. Esto no quiere decir que necesariamente el usuario vaya a experimentar siempre una mejora: puede darse el caso de que su navegador no posea ninguna copia previa y necesite descargar finalmente el fichero.

Finalmente, quedaría la duda sobre qué servicio de CDN utilizar. Yo, personalmente, aconsejo utilizar el de Google por la única razón de que es el más utilizado; esto aumenta las posibilidades de que el navegador cliente ya tenga una copia previa almacenada con respecto a otros servicios menos explotados como el de Microsoft.

Obviamente, deberíamos tener cuidado de no escoger un CDN más exótico que pueda desaparecer en cualquier momento; de hecho, ya el año pasado jQuery hizo saltar las alarmas de muchos desarrolladores cuando anunció que no continuaría ofreciendo este servicio. Frente a las protestas de éstos que argumentaban que muchas aplicaciones quedarían inutilizadas, jQuery rectificó y a día de hoy aún ofrece este servicio.

Es por todo esto que, respondiendo a la cuestión inicial, en un entorno de producción, el uso de un CDN para cargar bibliotecas como jQuery está plenamente justificado y es una práctica muy recomendable cara a la optimización en el lado cliente.

Más:

{13} Comentarios.

  1. Israel

    Una solución buena podría ser que los navegadores comprobasen con el checksum si ya han descargado el archivo en otra web.

  2. Benjamín

    ¿Pero para hacer el checksum del nuevo archivo te lo tendrás que descargar, no? En ese caso no ganamos nada, a lo sumo que no esté duplicado en la caché en tu disco duro. Otra opción es que CADA archivo tenga un checksum, pero lo veo bastante inviable.

    • Carlos Benítez

      Yo propondría otra cosa, pero es más utópica: que los navegadores funcionaran con paquetes en cliente predefinidos. Esto quiere decir que por ejemplo, cada navegador tuviese una versión de jQuery interna que actualizase solo cada vez que lo haga el repositorio general. Con esto, si se precisa el archivo, no habría que tirar de CDN sino directamente de caché.

      En pseudo-código sería algo así:

      // Calling browser library
      <script src="Browser::jQuery"></script>
      
      // Fall back if necessary
      <script>
      window.jQuery || document.write(unescape('%3Cscript src="/js_folder/jquery-1.6.1.min.js"%3E%3C/script%3E'))
      </script>
      

      Esto podría hacerse con las bibliotecas más usuales (Javascript y CSS) que tampoco son tantas. Con unas cien referencias, se cubriría de seguro más del 80% de los casos reales…

      Saludos!

  3. Israel

    Se podría poner el checksum en un atributo de la etiqueta script.

  4. Madman

    Estoy de acuerdo con Carlos. De hecho es un tema al que le doy vueltas desde hace bastante tiempo. Imagino que Chrome, Mozilla etc lo habrán pensado, ¿no? es inevitable no pensarlo, y la verdad, estaría muy muy bien.

    Por otro lado, también pienso que si esto fuese real ocurriría lo de siempre, habría navegadores que incluirían las bibliotecas y otros que no ,y al final, tendrías que añadirla la librería a tu proyecto de la forma tradicional o por CDN. Al final sería una manera más de incluirla, ¿no?

  5. leifsk8er

    ojala se os escuche ^^, de todas formas madman, podrias confirmar si se inicia el objeto jquery extrapolando el caso que comenta carlos en el articulo, en caso de que no inicie significa que el navegador no lo tiene incorporado, y entonces carga desde el cdn o desde el folder.

    Por cierto no tenia ni idea que sin http: esto tirase! :O Creia que era un error, pero he probado y tira!

  6. Madman

    Hola leifsk8er, a eso mismo me refería con cargar la librería de forma tradicional o por CDN.
    Y estoy contigo, ojalá se nos escuche XD

  7. NazarDesign

    Me ha encantado todo lo leído en este artículo y los acertados comentarios que lo complementan. Muy util este sitio. Saludos!

  8. castarco

    Una pequeña duda. ¿Qué puede ser mejor? Usar como fallback de una CDN otra CDN… ¿o el fichero local? ¿O mejor una “cascada” de fallbacks (no muy grande para no reducir el rendimiento) con CDNs hasta finalmente usar el fichero local?

    Lo digo porque parece improbable que caigan varias CDN a la vez :p .

    • Carlos Benítez

      Pues aquí hay varias cosas que tener en cuenta: si utilizamos una cascada de CDNs, a cada intento consumimos tiempo de ejecución, por lo que quizá no estamos consiguiendo el efecto deseado de acelerar una carga. Por otro lado, si utilizamos en dicha cascada servidores poco conocidos, es muy probable que el usuario no los tenga cacheados, por lo que tampoco obtenemos esa ventaja.

      Yo personalmente, utilizaría solo un CDN, el más popular según el recurso a cargar. En caso de fallo, pasaría directamente al archivo local. Sin embargo, si conocemos con certeza que hay dos servidores muy populares (Google y Microsoft por ejemplo) que ofrecen un mismo recurso de por sí es muy pesado (pensemos por ejemplo en una combinación de jQuery + jQueryUI), podríamos probar una cascada de ambos y pasar solo a la copia local en el improbable caso de que ninguno resuelva correctamente.

      Saludos.

  9. marcos

    Perfecta explicación, muy clarica. GRACIAS.

  10. Que te dire en verdad eso de cargara en ser de terceros es extraño yo lo hago pero hoy que tu me cuentas esto me pace pensar que si es la mejor manera de hacerlo facil y rapido talvez de alguna dificultad cuando lo trabajas local o no ???

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *