Carga combinada de jQuery: por CDN o en caso de fallo, por local

  • Por
Cómo cargar jQuery por CDN y en caso de no ser viable por cualquier motivo, recurrir a una copia en el servidor del framework, también llamado técnica fallback.
En este artículo mostraremos una manera optimizada de cargar la librería jQuery. Se trata de combinar dos tipos de acceso al framework comentados anteriormente en el artículo sobre las ventajas e inconvenientes de utilizar un CDN para incluir jQuery o un alojamiento en local de la librería.

Por un lado hablamos de la carga de jQuery a través de una red CDN y por otro lado la carga a través de nuestro propio servidor. Ambas opciones fueron descritas con detalle y comentados los pros y contras, por lo que ahora vamos a ampliar un poco la información presentando una manera nueva de cargar jQuery que aprovecha lo mejor de ambos métodos.

En principio siempre es mejor cargar jQuery a través de un CDN, que se supone que será mucho más rápido que nuestro propio servidor. Sin embargo, en caso de fallo del CDN por cualquier motivo, merece la pena ofrecer la posibilidad de acceder a jQuery a través de una copia de la librería en local. Esta técnica nos ofrece total seguridad ante el uso de una copia de jQuery o de otra librería traída desde un sitio web de terceros o CDN. La técnica que vamos a ver en este artículo es conocida como "fallback" y la vamos a implementar de diversas maneras, para que cada uno escoja aquella que mejor le parezca.

Optimizar la carga de jQuery con la solución proporcionada por Boilerplate

Boilerplate es un conjunto de herramientas y recursos para poder empezar a usar HTML5 con garantías. Muchos de los lectores deben conocerlo. Entre otras muchas cosas, hemos sacado de allí un método muy interesante para cargar jQuery, que es el que sigue.

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/jquery-1.7.1.min.js">x3C/script>')</script>

Como se puede ver, consiste en un par de scripts, colocados uno detrás de otro, que sirven para acceder a la librería jQuery por medio de dos fuentes. Primero se accede a un script externo, dentro de ajax.googleapis.com, que es el CDN proporcionado por Google Code. Ese CDN generalmente funcionará, pero en el caso que falle, tenemos el segundo script. En él se evalúa window.jQuery y en caso que de un estado negativo (solo será negativa la evaluación en el caso que jQuery no se haya podido cargar desde el CDN) se hace un document.write para colocar otra llamada a un script distinto, que contiene la librería, pero traía de nuestro propio servidor con una ruta relativa.

Nota: Quizás hayas reparado en la ruta del primer script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" y te haya extrañado que comience con dos barras. Eso no es un error de omisión del protocolo de comunicación, sino una URL absoluta que utiliza el mismo protocolo que la página que se esté consultando. Es decir, si estamos en un servidor seguro, el navegador accederá al script en la ruta https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js y si estamos en un servidor normal se accederá por el habitual http, en lugar de https.

Por este mismo motivo, si accedes al archivo HTML con el protocolo "file:" (es decir, hiciste doble click sobre el archivo HTML para ejecutar la copia que tienes en el disco duro, se intentaría acceder al CDN por file://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js y esa ruta nunca funcionaría. Osea, que este sistema de comenzar una ruta absoluta por dos barras inclindadas // te funcionará bien solo si estás accediendo al archivo a través de un servidor web.

De este modo podemos estar seguros que el script jQuery se traerá del lugar más óptimo, es decir, del CDN, y si no se puede, desde la ruta en nuestro propio servidor de alojamiento. Es una fórmula rápida, sencilla y extremamente efectiva de optimizar la carga de tu jQuery y se puede aplicar a cualquier otra librería que estés utilizando.

Este método lo hemos utilizado para la carga de jQuery en esta página de ejemplo.

Método optimizado de carga de jQuery con Modernizr.load

Modernizr es una librería Javascript que también te ofrece una serie de herramientas y utilidades que te vendrán como anillo al dedo cuando quieras desarrollar webs de la nueva generación en HTML5. Estamos tratando acerca de estas librerías en el Manual de Modernizr.

En este artículo os traemos un método de carga de jQuery a través del método load de Modernizr que ya se explicó brevemente en Modernizr.load() y la carga condicional de librerías Javascript y CSS. Sin embargo, en esta ocasión vamos a comentar un par de detalles y a hablar sobre un posible problema que podemos encontrarnos al utilizar esta técnica.

Nota: Es interesante comentar como referencia que el método load de Modernizr está desarrollado por autores diferentes del propio Modernizr. Se trata de un módulo implementado directamente en Modernizr llamado yepnope.js que es un cargador asíncrono y condicional de recursos que funciona sobre Javascript. Puedes saber más através de la propia web de yepnope.js.

Básicamente vamos a hacer lo mismo, intentar traernos jQuery desde el CDN y si falla usar una ruta de nuestro servidor. Pero antes de ver el código para hacer esto voy a comentar la ventaja que tiene este método y también el inconveniente que le veo.

Como parte positiva destacamos que este método de load de Modernizr es capaz de traerse en paralelo varios scripts, aunque luego se ejecutan secuencialmente, o por el orden que queramos. Incluso permite traernos scripts solo si se cumplen determinadas condiciones. Osea, es algo un poco más complejo que el método de Boilerplate, pero también bastante más versátil. En casos en los que estemos adquiriendo muchos archivos de script puede ser muy interesante, porque Modernizr.load se los descargará todos a la vez y no uno por uno, lo que seguramente ahorrará tiempo de carga en nuestra página con respecto a otros métodos de carga.

En la parte negativa de este método veo que te complica un poco las cosas a la hora de colocar scripts en la página. Debido a las características del método y la posibilidad de traerse condicionalmente unos scripts y otros, estamos obligados a colocar algunos scripts en lugares específicos, para que el propio flujo de carga y ejecución de las librerías funcione bien. Si colocamos scripts a la ligera, dispersos en el código de la página, posiblemente tengamos el problema de que se lleguen a ejecutar incluso antes que las librerías necesarias estén disponibles.

Comencemos observando este código:

Modernizr.load([
   {
      load: '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js',
      callback: function () {
         if ( !window.jQuery ) {
            Modernizr.load('js/jquery-1.7.1.min.js');
         }
      }
   },
   {
      load: 'js/js-necesita-jquery.js'
   }
]);

En esta llamada al método load tenemos la carga secuencial de dos grupos de scripts, definidos entre corchetes y enviados como parámetro a Modernizr.load. En el primer grupo hacemos la carga de jQuery y en el segundo grupo se trae una librería que necesita jQuery.

Nota: Como decía, todos esos scripts se descargan en serie, pero se ejecutan de manera secuencial.

Lo bonito está en la carga de jQuery por CDN y el enunciado "callback:" que nos permite indicar código a ejecutar cuando la carga del fichero ha sido realizada. El flujo de carga sería el siguiente.

Primero intentamos cargar jQuery desde el CDN con este código:

load: '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js',

Luego definimos una función callback para intentar comprobar si jQuery fue cargado correctamente.

callback: function () {
if ( !window.jQuery ) {
      Modernizr.load('js/jquery-1.7.1.min.js');
   }
}

Esta función callback se ejecuta después de que la carga anterior del CDN se haya completado, o en caso contrario, si se produjo un error o un timeout.

Nota: Si has leído la documentación de Modernizr quizás hayas notado que aquí estamos utilizando el enunciado "callback", mientras que ellos colocan el enunciado "complete". En principio complete debería funcionar, pero en la práctica no he conseguido un efecto deseable cuando falla la carga de jQuery desde el CDN. Ocurre que con "complete" se ejecutan los scripts que requieren jQuery sin haber esperado a cargar la copia local de las librerías. En GitHub el creador de yepnope (la librería que implementa el load en Modernizr) sugiere utilizar el "callback" y con ello conseguimos que funcione como se deseaba. En la misma nota comenta que este caso se resolverá en una versión más moderna de yepnope.js.

Simplemente, en caso que no exista window.jQuery se carga la librería desde local. Con esto podemos estar seguros que jQuery estará disponible, si no era en el CDN, al menos en la copia que tenemos en nuestro propio servidor.

A continuación tenemos el segundo bloque de script con una carga de un código que necesita jQuery para funcionar.

load: 'js/js-necesita-jquery.js'

Ese segundo bloque se ejecutará solo cuando el primer bloque haya terminado. Por supuesto, en el caso que el CDN hubiese fallado, se esperará a disponer la copia de jQuery local.

Nota: Ante un fallo del CDN, Modernizr tardará 10 segundos en acceder a la copia en local. Esto es porque algunos navegadores ofrecen el mismo tipo de señal ante una carga con éxito y ante un error. Por ello ellos han preferido utilizar un tiempo de timeout para saber si efectivamente una carga tuvo un error. Mientras espera el método load continua la descarga de otros scripts, pero no ejecuta nada hasta haber ejecutado la copia de jQuery que teníamos en local.

Puedes ver este ejemplo de técnica fallback con Modernizr.load en una página aparte.

Quizás todo esto te parezca mucho lio y demasicadas cosas a tener en cuenta para algo que Boilerplate soluciona de una manera más simple. Además, debido al flujo de ejecución del método Modernizr.load, estamos obligados a colocar en un lugar determinado todos aquellos scripts que requieran de jQuery. Por ello personalmente, si nuestro único objetivo es implementar el fallback de jQuery, para usar una copia en local cuando falla el CDN, preferiría el método de Boilerplate.

Ahora bien, podemos ver un segundo ejemplo de carga de liberías que puede que ofrezca un poco más de sentido a este método load. Imagina que estás desarrollando una página que usa decenas de scripts externos con plugins y que deseas cargarlos todos a la vez para ahorrar tiempo, en lugar de la carga secuencial que ofrecerían otros sistemas. Entonces podrías usar algo como esto.

Modernizr.load([{
load: '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js',
callback: function () {
   if (!window.jQuery) {
    Modernizr.load('js/jquery-1.7.1.min.js');
   }
}
}, {
load: ['js/jquery.animate-colors.js', 'js/jquery.easing.1.3.js'],
complete: function () {
   jQuery(function () {
      jQuery('#prueba').animate({
         color: "#fa4",
         "background-color": "#162"
      }, 3000, "easeOutElastic");
   });
}
}]);

Aquí tenemos un código muy parecido al anterior, con la salvedad que estamos usando un plugin adicional, aparte del propio script jQuery. En el primer bloque se carga jQuery o bien la copia "fallback" que tenemos en local (del mismo modo que antes). La diferencia es que ahora en el segundo bloque se carga un par de plugins y se utiliza un enunciado "complete" para definir el código que debe ejecutarse cuando se hayan cargado. Dentro de la función definida en el "complete" podemos colocar cualquier código que haga uso de esos plugins jQuery. Este esquema puede repetirse para cargar no solo dos plugins, sino varios, y la carga se realizará en paralelo.

Este segundo ejemplo de Modernizr.load lo podemos ver en una página aparte.

Conclusión

Sin lugar a dudas, con estas técnicas ya no hay escusa para usar un hospedaje de archivos CDN sin preocuparse de eventuales problemas, porque siempre contarás con una copia en local para solventarlos. El sistema de Boilerplate es muy sencillo y usable sin prácticamente ninguna modificación en un sitio web y el sistema de Modernizr un poco más complejo, pero que requerirá pensar las cosas de una manera distinta a como las vienes realizando.

Hasta aquí la referencia para saber como se puede combinar el hosting CDN y el local de jQuery para optimizar la carga.

Autor

Miguel Angel Alvarez

Miguel es fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Comenzó en el mundo del desarrollo web en el año 1997, transformando su hobby en su trabajo.

Compartir

Comentarios

BaLanZe

26/5/2012
Fallo en parte del código
Hola! Ante todo felicitaros por esta maravillosa página con la que me estoy poniendo al día con JQuery.

Comentaros que en el ejemplo de carga de JQuery mediante fallback al principio del artículo hay un error en la siguiente línea:

<script>window.jQuery || document.write('<script src="js/jquery-1.7.1.min.js"[b]>x3C[/b]/script>')</script>

La sentencia de escape correcta para sustituir el < es [b]x3c[/b]. Se os pasó el ''.

Muchas gracias de nuevo y un saludo!

reperly

26/1/2013
Carga de jQuery
He estado haciendo pruebas con las diversas maneras de cargar jQuery en la página web, y al final he encontrado como la más sencilla y fiable esta:
<script src="http://code.jquery.com/jquery-1.9.0.js"></script>
Funciona con todos los navegadores, aunque IE, con su natural manera de ser, intenta no admitir scripts mientras no se lo autorices expresamente.
Gracias por el manual. Es magnífico

UnderWorld

16/5/2016
Cargar CSS si falla el CDN
hola, soy aprendiz de programador web, y he encontrado cosas muy utiles en su pagina, me gustaria saber si me puede ayudar con este caso, estoy creando un site con boilerplate y bootstrap, y quisiera que como mismo hace el fallback para el jquery se puede hacer con el bootstrap.js y los CCS de bootstrap para los cuales puedo usar CDNs tambien, pero quisiera que se puedieran cargar en local tambien, ya que parte del publico que tendra ese site no tiene acceso a los CDNs.