Il modo migliore per utilizzare jQuery ospitato da Google, ma fallire nella mia libreria ospitata su Google

StackOverflow https://stackoverflow.com/questions/1014203

Domanda

Quale sarebbe un buon modo per tentare di caricare il jQuery ospitato su Google (o altre librerie ospitate da Google), ma carica la mia copia di jQuery se il tentativo di Google fallisce?

Non sto dicendo che Google sia traballante. Ci sono casi in cui la copia di Google è bloccata (apparentemente in Iran, ad esempio).

Dovrei impostare un timer e verificare l'oggetto jQuery?

Quale sarebbe il pericolo di entrambe le copie?

Non sto davvero cercando risposte come " usa solo Google " o " basta usare il proprio. " Capisco questi argomenti. Comprendo anche che è probabile che l'utente abbia la versione di Google memorizzata nella cache. Sto pensando ai fallback per il cloud in generale.


Modifica: questa parte è stata aggiunta ...

Poiché Google suggerisce di utilizzare google.load per caricare le librerie ajax e al termine esegue una richiamata, mi chiedo se questa è la chiave per serializzare questo problema.

So che sembra un po 'folle. Sto solo cercando di capire se può essere fatto in modo affidabile o meno.


Aggiornamento: jQuery ora è ospitato sul CDN di Microsoft.

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

È stato utile?

Soluzione

Puoi raggiungerlo in questo modo:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<script>
   window.jQuery || document.write('<script src="/path/to/your/jquery"><\/script>');
</script>

Questo dovrebbe essere nella tua pagina <head> e tutti i gestori di eventi pronti per jQuery dovrebbero trovarsi in <body> per evitare errori (anche se non è infallibile!).

Un motivo in più per non utilizzare jQuery ospitato su Google è che in alcuni paesi il nome di dominio di Google è vietato.

Altri suggerimenti

Il modo più semplice e pulito per farlo di gran lunga:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="path/to/your/jquery"><\/script>')</script>

Questo sembra funzionare per me:

<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
// has the google object loaded?
if (window.google && window.google.load) {
    google.load("jquery", "1.3.2");
} else {
    document.write('<script type="text/javascript" src="http://joecrawford.com/jquery-1.3.2.min.js"><\/script>');
}
window.onload = function() {
    $('#test').css({'border':'2px solid #f00'});
};
</script>
</head>
<body>
    <p id="test">hello jQuery</p>
</body>
</html>

Il modo in cui funziona è utilizzare l'oggetto google che chiama http://www.google.com/ jsapi si carica sull'oggetto window. Se quell'oggetto non è presente, supponiamo che l'accesso a Google non riesca. In tal caso, carichiamo una copia locale utilizzando document.write. (sto usando il mio server in questo caso, per favore usa il tuo per testarlo).

Ho anche testato la presenza di window.google.load - Potrei anche fare un controllo typeof per vedere che le cose sono oggetti o funzioni come appropriato. Ma penso che questo faccia il trucco.

Ecco solo la logica di caricamento, poiché l'evidenziazione del codice sembra fallire da quando ho pubblicato l'intera pagina HTML che stavo testando:

if (window.google && window.google.load) {
    google.load("jquery", "1.3.2");
} else {
    document.write('<script type="text/javascript" src="http://joecrawford.com/jquery-1.3.2.min.js"><\/script>');
}

Anche se devo dire, non sono sicuro che se questo è un problema per i visitatori del tuo sito dovresti avere a che fare con la API AJAX Libraries Google .

Curiosità : Inizialmente ho provato a utilizzare un blocco try..catch per questo in varie versioni, ma non sono riuscito a trovare una combinazione così pulita. Sarei interessato a vedere altre implementazioni di questa idea, puramente come un esercizio.

Se hai modernizr.js incorporato nel tuo sito, puoi utilizzare yepnope.js integrato per caricare gli script in modo asincrono, tra gli altri jQuery (con fallback).

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();
    }
}]);

Questo carica jQuery da Google-cdn. Successivamente viene controllato, se jQuery è stato caricato correttamente. In caso contrario (& Quot; nope & Quot;), viene caricata la versione locale. Vengono caricati anche i tuoi script personali: il & Quot; entrambi & Quot; indica che il processo di caricamento viene avviato indipendentemente dal risultato del test.

Quando tutti i processi di caricamento sono completi, viene eseguita una funzione, nel caso 'MyApp.init'.

Personalmente preferisco questo modo di caricare script asincroni. E poiché faccio affidamento sui test di funzionalità forniti da modernizr durante la costruzione di un sito, lo ho comunque incorporato nel sito. Quindi in realtà non ci sono spese generali.

Ci sono alcune ottime soluzioni qui, ma mi piacerebbe fare un ulteriore passo avanti riguardo al file locale.

In uno scenario in cui Google fallisce, dovrebbe caricare una fonte locale ma forse un file fisico sul server non è necessariamente l'opzione migliore. Ne ho parlato perché attualmente sto implementando la stessa soluzione, solo io voglio tornare a un file locale che viene generato da un'origine dati.

Le mie ragioni sono che voglio avere un po 'di idea quando si tratta di tenere traccia di ciò che carico da Google rispetto a ciò che ho sul server locale. Se voglio cambiare versione, voglio mantenere la mia copia locale sincronizzata con ciò che sto cercando di caricare da Google. In un ambiente in cui ci sono molti sviluppatori, penso che l'approccio migliore sarebbe quello di automatizzare questo processo in modo che tutto ciò che uno dovrebbe fare è cambiare un numero di versione in un file di configurazione.

Ecco la mia soluzione proposta che dovrebbe funzionare in teoria:

  • In un file di configurazione dell'applicazione, memorizzerò 3 cose: l'URL assoluto per la libreria, l'URL per l'API JavaScript e il numero di versione
  • Scrivi una classe che ottiene il contenuto del file della libreria stessa (ottiene l'URL dalla configurazione dell'app), lo memorizza nella mia origine dati con il nome e il numero di versione
  • Scrivi un gestore che estrae il mio file locale dal db e memorizza nella cache il file fino a quando non cambia il numero di versione.
  • Se cambia (nella mia configurazione dell'app), la mia classe estrarrà il contenuto del file in base al numero di versione, lo salverà come nuovo record nella mia origine dati, quindi il gestore avvierà e servirà la nuova versione.

In teoria, se il mio codice è scritto correttamente, tutto ciò che dovrei fare è cambiare il numero di versione nella mia configurazione dell'app quindi viola! Hai una soluzione di fallback che è automatizzata e non devi conservare i file fisici sul tuo server.

Cosa pensano tutti? Forse questo è eccessivo, ma potrebbe essere un metodo elegante per mantenere le tue librerie AJAX.

Acorn

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);

}

Dopo aver tentato di includere la copia di Google dalla CDN.

In HTML5, non è necessario impostare l'attributo type.

Puoi anche usare ...

window.jQuery || document.write('<script src="/libs/jquery.js"><\/script>');

Potresti voler usare il tuo file locale come ultima risorsa.

Sembra che la CDN di jQuery non supporti https. In tal caso, potresti voler caricare prima da lì.

Quindi, ecco la sequenza: Google CDN = & Gt; Microsoft CDN = & Gt; La tua copia locale.

<!-- load jQuery from Google's CDN -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> 
<!-- fallback to Microsoft's Ajax CDN -->
<script> window.jQuery || document.write('<script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.3.min.js">\x3C/script>')</script> 
<!-- fallback to local file -->
<script> window.jQuery || document.write('<script src="Assets/jquery-1.8.3.min.js">\x3C/script>')</script> 

Carica condizionalmente la versione jQuery più recente / legacy e il fallback:

<!--[if lt IE 9]>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="/public/vendor/jquery-legacy/dist/jquery.min.js">\x3C/script>')</script>
<![endif]-->
<!--[if gte IE 9]><!-->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="/public/vendor/jquery/dist/jquery.min.js">\x3C/script>')</script>
<!--<![endif]-->
  • Passaggio 1: jQuery non è stato caricato? (controlla jQuery variabile)

Come controllare una variabile non definita in JavaScript

  • Passaggio 2: importare dinamicamente (il backup) il file javascript

Come posso includere un file JavaScript in un altro file JavaScript?

A causa del problema di messa al bando di Google, preferisco usare il cdn di Microsoft http://www.asp.net/ajaxlibrary/cdn.ashx

Ecco una grande spiegazione su questo!

Implementa anche ritardi nel caricamento e timeout!

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

Per coloro che usano ASP.NET MVC 5, aggiungi questo codice nel tuo BundleConfig.cs per abilitare il CDN per 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);

UPDATE:
Questa risposta si è rivelata sbagliata. Si prega di consultare i commenti per la vera spiegazione.


Alla maggior parte delle domande è stata data risposta, ma per quanto riguarda la parte finale:

  

Quale sarebbe il pericolo di entrambe le copie?

Nessuno davvero. Sprecheresti la larghezza di banda, potresti aggiungere alcuni millisecondi scaricando una seconda copia inutile, ma non ci sarebbe alcun danno reale se arrivassero entrambi. Ovviamente dovresti evitarlo usando le tecniche sopra menzionate.

Ho creato un Gist che dovrebbe caricare dinamicamente jQuery se non è già caricato, e se l'origine fallisce, procede su fallback (cuciti insieme da molte risposte): https://gist.github.com/tigerhawkvok/9673154

Nota che ho intenzione di mantenere aggiornato Gist ma non questa risposta, per quello che 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();
}

jQuery ospitato su Google

  • Se ti interessano i browser meno recenti, principalmente le versioni di IE precedenti a IE9, questa è la versione jQuery più ampiamente compatibile
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  • Se non & # 8217; non preoccuparti di oldIE, questo è più piccolo e più veloce:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

Piano di backup / fallback!

  • Ad ogni modo, dovresti utilizzare un fallback a local nel caso in cui la CDN di Google fallisca (improbabile) o sia bloccata in una posizione da cui i tuoi utenti accedono al tuo sito (leggermente più probabile), come l'Iran o talvolta la Cina.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>if (!window.jQuery) { document.write('<script src="/path/to/your/jquery"><\/script>'); }
</script>

Riferimento: http://websitepeedoptimizations.com/ContentDeliveryNetworkPost.aspx

Ritengo che dovrebbe sfuggire all'ultimo < a \ x3C nella stringa. Quando il browser vede, considera che questa è la fine del blocco di script (poiché il parser HTML non ha idea di JavaScript, non è in grado di distinguere tra qualcosa che appare in una stringa e qualcosa che in realtà è destinato a terminare lo script elemento). Quindi apparire letteralmente in JavaScript all'interno di una pagina HTML (nel migliore dei casi) causerà errori e (nel peggiore dei casi) sarà un enorme buco nella sicurezza.

<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js"></script>
<script>window.jQuery || document.write('<script src="js/jquery-2.0.0.min.js">\x3C/script>')</script>
if (typeof jQuery == 'undefined')) { ...

o

if(!window.jQuery){

Non funzionerà se la versione cdn non è caricata, perché il browser eseguirà questa condizione e durante il download continuerà a scaricare il resto dei javascripts che richiedono jQuery e restituiscono errori. La soluzione era caricare gli script attraverso quella condizione.

    <script src="http://WRONGPATH.code.jquery.com/jquery-1.4.2.min.js" type="text/javascript"></script><!--  WRONGPATH for test-->
  <script type="text/javascript">
  function loadCDN_or_local(){
    if(!window.jQuery){//jQuery not loaded, take a local copy of jQuery and then my scripts
      var scripts=['local_copy_jquery.js','my_javascripts.js'];
      for(var i=0;i<scripts.length;i++){
      scri=document.getElementsByTagName('head')[0].appendChild(document.createElement('script'));
      scri.type='text/javascript';
      scri.src=scripts[i];
    }
  }
  else{// jQuery loaded can load my scripts
    var s=document.getElementsByTagName('head')[0].appendChild(document.createElement('script'));
    s.type='text/javascript';
    s.src='my_javascripts.js';
  }
  }
  window.onload=function(){loadCDN_or_local();};
  </script>

Utilizzando la sintassi di Razor in ASP.NET, questo codice fornisce supporto di fallback e funziona con una radice virtuale:

@{var jQueryPath = Url.Content("~/Scripts/jquery-1.7.1.min.js");}
<script type="text/javascript">
    if (typeof jQuery == 'undefined')
        document.write(unescape("%3Cscript src='@jQueryPath' type='text/javascript'%3E%3C/script%3E"));
</script>

O crea un aiuto ( panoramica dell'helper ):

@helper CdnScript(string script, string cdnPath, string test) {
    @Html.Raw("<script src=\"http://ajax.aspnetcdn.com/" + cdnPath + "/" + script + "\" type=\"text/javascript\"></script>" +
        "<script type=\"text/javascript\">" + test + " || document.write(unescape(\"%3Cscript src='" + Url.Content("~/Scripts/" + script) + "' type='text/javascript'%3E%3C/script%3E\"));</script>")
}

e usalo in questo modo:

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

Anche se scrivere document.write("<script></script>") sembra più facile per il backoff di jQuery, Chrome fornisce un errore di convalida in quel caso. Quindi preferisco rompere & Quot; script & Quot; parola. Quindi diventa più sicuro come sopra.

<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.1.min.js"></script>
<script>if (typeof jQuery === "undefined") {
   window.jqFallback = true;
   document.write("<scr"+"ipt src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js'></scr"+"ipt>");
} </script>

Per problemi a lungo termine, sarebbe meglio registrare i fallback di JQuery. Nel codice sopra, se il primo CDN non è disponibile, JQuery viene caricato da un altro CDN. Ma potresti voler conoscere quel CDN errato e rimuoverlo permanentemente. (questo caso è un caso molto eccezionale) Inoltre è meglio registrare i problemi di fallback. Quindi puoi inviare casi errati con AJAX. Poiché JQuery non è definito, è necessario utilizzare javascript alla vaniglia per la richiesta AJAX.

<script type="text/javascript">
    if (typeof jQuery === 'undefined' || window.jqFallback == true) {
        // XMLHttpRequest for IE7+, Firefox, Chrome, Opera, Safari
        // ActiveXObject for IE6, IE5
        var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
        var url = window.jqFallback == true ? "/yourUrl/" : "/yourUrl2/";
        xmlhttp.open("POST", url, true);
        xmlhttp.send();
    }
</script>

L'incapacità di caricare la risorsa da un archivio dati esterno al di fuori del proprio controllo è difficile. Cercare funzioni mancanti è totalmente fallace come mezzo per evitare di soffrire un timeout, come descritto qui: http://www.tech-101.com/ support / topic / 4499-issues-using-a-cdn /

Ancora un altro fallback che sostituisce 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('<script src="' + src + '"></script>');
    }
})(document, window.jQuery || window.Zepto);
  • È possibile attenersi a una versione jQuery specificandola nella stringa
  • Perfetto per la gestione delle risorse che non funziona con i tag HTML
  • Testato in natura - funziona perfettamente per gli utenti dalla Cina

Puoi usare un codice come:

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>window.jQuery || document.write('<script type="text/javascript" src="./scripts/jquery.min.js">\x3C/script>')</script>

Ma ci sono anche librerie che puoi usare per impostare diversi possibili fallback per i tuoi script e ottimizzare il processo di caricamento:

  • basket.js
  • RequireJS
  • yepnope

Esempi:

basket.js Penso che la variante migliore per ora. Memorizzerà la cache dello script nel localStorage, accelerando i caricamenti successivi. La chiamata più semplice:

basket.require({ url: '/path/to/jquery.js' });

Questo restituirà una promessa e puoi fare la prossima chiamata in caso di errore o caricare le dipendenze in caso di successo:

basket
    .require({ url: '/path/to/jquery.js' })
    .then(function () {
        // Success
    }, function (error) {
        // There was an error fetching the script
        // Try to load jquery from the next cdn
    });

RequireJS

requirejs.config({
    enforceDefine: true,
    paths: {
        jquery: [
            '//ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min',
            //If the CDN location fails, load from this location
            'js/jquery-2.0.0.min'
        ]
    }
});

//Later
require(['jquery'], function ($) {
});

yepnope

yepnope([{
  load: 'http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js',
  complete: function () {
    if (!window.jQuery) {
      yepnope('js/jquery-2.0.0.min.js');
    }
  }
}]);

Quasi tutti i CDN pubblici sono abbastanza affidabili. Tuttavia, se sei preoccupato per il dominio google bloccato, puoi semplicemente eseguire il fallback ad altri CDN pubblici come PageCDN , CDNJS o jsDelivr :

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
   window.jQuery || document.write('<script src="https://pagecdn.io/lib/jquery/3.2.1/jquery.min.js"><\/script>');
</script>

Tuttavia, in tal caso, potresti preferire utilizzare qualche altra CDN come opzione preferita e fallback a Google CDN per evitare richieste non soddisfatte e tempi di attesa:

<script src="https://pagecdn.io/lib/jquery/3.2.1/jquery.min.js"></script>
<script>
   window.jQuery || document.write('<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"><\/script>');
</script>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top