La mejor forma de utilizar jQuery alojado en Google, pero volver a caer en mi biblioteca alojada en Google falla

¿Cuál sería una buena manera de intentar cargar el jQuery alojado en Google (u otras bibliotecas alojadas en Google), pero cargar mi copia de jQuery si falla el bash de Google?

No digo que Google sea escamoso. Hay casos en que la copia de Google está bloqueada (aparentemente en Irán, por ejemplo).

¿Configuraría un temporizador y verificaría el objeto jQuery?

¿Cuál sería el peligro de que lleguen ambas copias?

Realmente no busca respuestas como “solo use Google” o “solo use la suya”. Entiendo esos argumentos También entiendo que es probable que el usuario tenga la versión de Google en la memoria caché. Estoy pensando en retrocesos para la nube en general.


Editar: Esta parte agregó …

Dado que Google sugiere usar google.load para cargar las bibliotecas de AJAX, y realiza una callback una vez hecho, me pregunto si esa es la clave para serializar este problema.

Sé que suena un poco loco. Solo estoy tratando de descubrir si se puede hacer de manera confiable o no.


Actualización: jQuery ahora alojado en CDN de Microsoft.

http://www.asp.net/ajax/cdn/

Puedes lograrlo así:

  

Esto debe estar en su página y cualquier manejador de eventos jQuery ready debe estar en para evitar errores (¡aunque no es infalible!).

Una razón más para no utilizar jQuery alojado en Google es que en algunos países, el nombre de dominio de Google está prohibido.

La forma más fácil y limpia de hacer esto de lejos:

   

Esto parece funcionar para mí:

       

hello jQuery

La forma en que funciona es usar el objeto google que carga http://www.google.com/jsapi en el objeto window . Si ese objeto no está presente, estamos asumiendo que el acceso a Google está fallando. Si ese es el caso, cargamos una copia local usando document.write . (Estoy usando mi propio servidor en este caso, por favor use el suyo para probar esto).

También compruebo la presencia de window.google.load . También podría hacer una comprobación de tipo para ver si las cosas son objetos o funciones, según corresponda. Pero creo que esto hace el truco.

Aquí está solo la lógica de carga, ya que el resaltado del código parece fallar ya que publiqué toda la página HTML que estaba probando:

 if (window.google && window.google.load) { google.load("jquery", "1.3.2"); } else { document.write(' 

Aunque debo decir que no estoy seguro de que, si esto es una preocupación para los visitantes de su sitio, debería estar jugando con la API de bibliotecas AJAX de Google .

Dato curioso : Intenté usar inicialmente un bloque try..catch para esto en varias versiones, pero no pude encontrar una combinación tan clara como esta. Me interesaría ver otras implementaciones de esta idea, puramente como un ejercicio.

Si tiene modernizr.js incrustado en su sitio, puede usar el yepnope.js incorporado para cargar sus scripts de forma asincrónica, entre otros jQuery (con respaldo).

 Modernizr.load([{ load : '//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js' },{ test : window.jQuery, nope : 'path/to/local/jquery-1.7.2.min.js', both : ['myscript.js', 'another-script.js'], complete : function () { MyApp.init(); } }]); 

Esto carga jQuery del Google-cdn. Luego se verifica si jQuery se cargó correctamente. Si no (“nope”), se carga la versión local. También se cargan sus scripts personales; el “both” indica que el proceso de carga se inicia independientemente del resultado de la prueba.

Cuando se completan todos los procesos de carga, se ejecuta una función, en el caso ‘MyApp.init’.

Personalmente, prefiero esta forma de carga de scripts asincrónicos. Y como confío en las pruebas de funciones proporcionadas por modernizr cuando construyo un sitio, lo tengo incorporado en el sitio de todos modos. Entonces no hay gastos generales.

 if (typeof jQuery == 'undefined') { // or if ( ! window.jQuery) // or if ( ! 'jQuery' in window) // or if ( ! window.hasOwnProperty('jQuery')) var script = document.createElement('script'); script.type = 'text/javascript'; script.src = '/libs/jquery.js'; var scriptHook = document.getElementsByTagName('script')[0]; scriptHook.parentNode.insertBefore(script, scriptHook); } 

Después de intentar incluir la copia de Google desde el CDN.

En HTML5, no necesita establecer el atributo de type .

También puedes usar…

 window.jQuery || document.write(' 

Aquí hay algunas soluciones geniales, pero me gustaría dar un paso más con respecto al archivo local.

En un escenario en el que Google falla, debe cargar una fuente local, pero tal vez un archivo físico en el servidor no sea necesariamente la mejor opción. Lo menciono porque actualmente estoy implementando la misma solución, solo quiero recurrir a un archivo local generado por una fuente de datos.

Mis razones para esto es que quiero tener algo de tranquilidad cuando se trata de hacer un seguimiento de lo que cargo de Google frente a lo que tengo en el servidor local. Si deseo cambiar las versiones, querré que mi copia local se sincronice con lo que bash cargar de Google. En un entorno en el que hay muchos desarrolladores, creo que el mejor enfoque sería automatizar este proceso para que todo lo que uno deba hacer sea cambiar un número de versión en un archivo de configuración.

Aquí está mi solución propuesta que debería funcionar en teoría:

  • En un archivo de configuración de la aplicación, almacenaré 3 cosas: URL absoluta para la biblioteca, la URL para la API de JavaScript y el número de versión
  • Escriba una clase que obtenga el contenido del archivo de la biblioteca (obtiene la URL de la configuración de la aplicación), la almacena en mi fuente de datos con el nombre y el número de versión
  • Escriba un controlador que extraiga mi archivo local de la base de datos y guarde en caché el archivo hasta que cambie el número de versión.
  • Si cambia (en la configuración de mi aplicación), mi clase extraerá el contenido del archivo en función del número de versión, lo guardará como un nuevo registro en mi fuente de datos, y luego el controlador iniciará y publicará la nueva versión.

En teoría, si mi código está escrito correctamente, todo lo que tendría que hacer es cambiar el número de versión en la configuración de mi aplicación y luego ¡viola! Usted tiene una solución alternativa que es automática, y no tiene que mantener archivos físicos en su servidor.

¿Qué piensan todos? Tal vez esto sea excesivo, pero podría ser un método elegante para mantener sus bibliotecas AJAX.

Bellota

Es posible que desee utilizar su archivo local como último recurso.

Parece que a partir de ahora el propio CDN de jQuery no es compatible con https. Si lo hizo, entonces es posible que desee cargar desde allí primero.

Así que aquí está la secuencia: Google CDN => Microsoft CDN => Tu copia local.

       

Cargue condicionalmente la última versión heredada de jQuery y la alternativa:

      
  • Paso 1: ¿jQuery no se cargó? (verifique la variable jQuery )

Cómo verificar una variable no definida en JavaScript

  • Paso 2: importar dinámicamente (la copia de seguridad) archivo javascript

¿Cómo incluyo un archivo JavaScript en otro archivo JavaScript?

Debido al problema de prohibición de Google, prefiero usar cdn de Microsoft http://www.asp.net/ajaxlibrary/cdn.ashx

¡Aquí hay una gran explicación sobre esto!

¡También implementa demoras y tiempos de espera de carga!

http://happyworm.com/blog/2010/01/28/a-simple-and-robust-cdn-failover-for-jquery-14-in-one-line/

Para aquellas personas que usan ASP.NET MVC 5, agregue este código en su BundleConfig.cs para habilitar el CDN para jquery:

 bundles.UseCdn = true; Bundle jqueryBundle = new ScriptBundle("~/bundles/jquery", "//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js").Include("~/Scripts/jquery-{version}.js"); jqueryBundle.CdnFallbackExpression = "window.jQuery"; bundles.Add(jqueryBundle); 

ACTUALIZAR:
Esta respuesta resultó ser incorrecta. Por favor vea los comentarios para la explicación real.


La mayoría de su pregunta ha sido respondida, pero en cuanto a la parte final:

¿Cuál sería el peligro de que lleguen ambas copias?

Ninguno realmente Perderías ancho de banda, podrías agregar algunos milisegundos para descargar una segunda copia inútil, pero no hay daño real si ambos salen adelante. Debería, por supuesto, evitar esto usando las técnicas mencionadas anteriormente.

Google Hosted jQuery

  • Si le interesan los navegadores más antiguos, principalmente las versiones de IE anteriores a IE9, esta es la versión de jQuery más compatible.
  
  • Si no te importa oldIE, este es más pequeño y más rápido:
  

Plan de respaldo / respaldo

  • De cualquier forma, debe usar una alternativa a local en caso de que Google CDN falle (poco probable) o se bloquee en una ubicación a la que sus usuarios accedan a su sitio (algo más probable), como Irán o, a veces, China.
   

Referencia: http://websitespeedoptimizations.com/ContentDeliveryNetworkPost.aspx

Considero que debería escapar de la última

   

 if (typeof jQuery == 'undefined')) { ... 

O

 if(!window.jQuery){ 

No funcionará si la versión cdn no está cargada, porque el navegador ejecutará esta condición y durante la misma seguirá descargando el rest de javascripts que necesita jQuery y devuelve el error. La solución era cargar scripts a través de esa condición.

    

Usando la syntax de Razor en ASP.NET, este código proporciona soporte de respaldo y funciona con una raíz virtual:

 @{var jQueryPath = Url.Content("~/Scripts/jquery-1.7.1.min.js");}  

O haz una ayuda ( descripción general del ayudante ):

 @helper CdnScript(string script, string cdnPath, string test) { @Html.Raw("" + "") } 

y úsalo así:

 @CdnScript("jquery-1.7.1.min.js", "ajax/jQuery", "window.jQuery") @CdnScript("jquery.validate.min.js", "ajax/jquery.validate/1.9", "jQuery.fn.validate") 

Hice un Gist que debería cargar dinámicamente jQuery si aún no está cargado, y si la fuente falla, procede a errores (cosidos a partir de muchas respuestas): https://gist.github.com/tigerhawkvok/9673154

Tenga en cuenta que planeo mantener el Gist actualizado, pero no esta respuesta, ¡por lo que vale!

 /* See https://gist.github.com/tigerhawkvok/9673154 for the latest version */ function cascadeJQLoad(i) { // Use alternate CDNs where appropriate to load jQuery if (typeof(i) != "number") i = 0; // the actual paths to your jQuery CDNs var jq_paths = [ "ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js", "ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.min.js" ]; // Paths to your libraries that require jQuery var dependent_libraries = [ "js/c.js" ]; if (window.jQuery === undefined && i < jq_paths.length) { i++; loadJQ(jq_paths[i], i, dependent_libraries); } if (window.jQuery === undefined && i == jq_paths.length) { // jQuery failed to load // Insert your handler here } } /*** * You shouldn't have to modify anything below here ***/ function loadJQ(jq_path, i, libs) { //load jQuery if it isn't already if (typeof(jq_path) == "undefined") return false; if (typeof(i) != "number") i = 1; var loadNextJQ = function() { var src = 'https:' == location.protocol ? 'https' : 'http'; var script_url = src + '://' + jq_path; loadJS(script_url, function() { if (window.jQuery === undefined) cascadeJQLoad(i); }); } window.onload = function() { if (window.jQuery === undefined) loadNextJQ(); else { // Load libraries that rely on jQuery if (typeof(libs) == "object") { $.each(libs, function() { loadJS(this.toString()); }); } } } if (i > 0) loadNextJQ(); } function loadJS(src, callback) { var s = document.createElement('script'); s.src = src; s.async = true; s.onreadystatechange = s.onload = function() { var state = s.readyState; try { if (!callback.done && (!state || /loaded|complete/.test(state))) { callback.done = true; callback(); } } catch (e) { // do nothing, no callback function passed } }; s.onerror = function() { try { if (!callback.done) { callback.done = true; callback(); } } catch (e) { // do nothing, no callback function passed } } document.getElementsByTagName('head')[0].appendChild(s); } /* * The part that actually calls above */ if (window.readyState) { //older microsoft browsers window.onreadystatechange = function() { if (this.readyState == 'complete' || this.readyState == 'loaded') { cascadeJQLoad(); } } } else { //modern browsers cascadeJQLoad(); } 

Aunque escribir document.write("") parece más fácil para el backoff de jQuery, Chrome da un error de validación en ese caso. Por lo tanto, prefiero romper la palabra “guión”. Entonces se vuelve más seguro como arriba.

   

Para problemas a largo plazo, sería mejor registrar los repliegues de JQuery. En el código anterior, si el primer CDN no está disponible, JQuery se carga desde otro CDN. Pero es posible que desee conocer esa CDN errónea y eliminarla permanentemente. (este caso es muy excepcional) También es mejor registrar problemas de respaldo. Para que pueda enviar casos erróneos con AJAX. Debido a que JQuery no está definido, debe usar vainilla javascript para la solicitud de AJAX.

  

La incapacidad de cargar el recurso desde un almacén de datos externo más allá de su control es difícil. Buscar funciones faltantes es totalmente falaz como una forma de evitar el tiempo de espera, como se describe aquí: http://www.tech-101.com/support/topic/4499-issues-using-a-cdn/

Sin embargo, otra alternativa que reemplaza ajax.googleapis.com con cdnjs.cloudflare.com :

 (function (doc, $) { 'use strict'; if (typeof $ === 'undefined') { var script = doc.querySelector('script[src*="jquery.min.js"]'), src = script.src.replace('ajax.googleapis.com', 'cdnjs.cloudflare.com'); script.parentNode.removeChild(script); doc.write(''); } })(document, window.jQuery || window.Zepto); 
  • No tiene que preocuparse por la versión jQuery
  • Perfecto para Asset Management que no funciona con snips HTML
  • Probado en la naturaleza: funciona perfecto para usuarios de China