> Manuales > Manual de jQuery

Optimización de carga de jQuery por CDN y su fallback para la carga local de la librería, en caso que no sea viable usar el CDN por cualquier motivo.

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

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.

En aquel artículo explicamos por un lado 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 Resumen vamos a ver dos soluciones optimizadas para la carga de jQuery:

Para los lectores que sois nuevos en jQuery, quizás sea un artículo un poco más avanzado de lo que correspondería al momento en el que estamos en el Manual de jQuery. Si estás leyendo el manual artículo a artículo podrías saltarte este artículo y leerlo más adelante.

Pero en resumen, antes de comenzar, queremos señalar que entre los dos métodos que ofrecemos en este artículo, el primero es muy útil y sencillo. Puedes implementarlo en tu sitio web y obtener una ventaja relevante.

El segundo método, el que está basado en Modernizr quizás es demasiado complejo para lo que ofrece. Es una práctica que podría venir bien porque permite la descarga de todo el Javascript de la página en paralelo, aunque luego se ejecute en secuencial. No obstante, requiere la carga de una librería extra, el propio Modernizr, por lo que, si no usas esa librería para otras cosas, me parece un gasto innecesario en tiempo de descarga para los beneficios que se irán a obtener.

Dicho esto, os dejamos con los métodos de carga combinada de jQuery: CDN + Carga de la librería en local.

Tecnica de fallback para la carga de jQuery

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.

Se basa en estos hechos:

El fallback es justamente la técnica que te ofrece una segunda vía, que debería de funcionar cuando la primera ha fallado. Gracias a esta técnica conseguimos total seguridad en la carga de jQuery, oferciendo una vía de escape cuando por cualquier cuestión la carga desde el CDN no haya podido funcionar.

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/3.6.3/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/jquery.min.js">\x3C/script>')</script>

En el código anterior tienes un \x3C/scriptdentro del método document.write(). Eso puede parecer un error pero no lo es. El motivo es que no podemos colocar un </script> dentro de la cadena que queremos escribir en la página, porque se entendería que se está cerrando el bloque de script del código HTML y no queremos eso. Por eso, para escapar el cierre de la etiqueta <script> se usan esos caracteres. Espero que se entienda.

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.

Nota:

Quizás hayas reparado en la ruta del primer script, en el atributo src, y te haya extrañado que comience con dos barras:

src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"

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. No obstante, gracias a que tenemos el fallback, no habrá problemas para cargar jQuery en local a través de la copia que tenemos en nuestro proyecto.

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.

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 paralelo, 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.

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

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

2) 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.

¿Qué método de fallback es preferible?

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.

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.

Miguel Angel Alvarez

Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...

Manual