Der beste Weg, um Googles gehostete jQuery zu verwenden, aber auf meine gehostete Bibliothek bei Google zurückzugreifen, schlägt fehl

1016

Was wäre ein guter Weg, um zu versuchen, die gehostete jQuery bei Google (oder anderen von Google gehosteten Bibliotheken) zu laden, aber meine Kopie von jQuery zu laden, wenn der Google-Versuch fehlschlägt?

Ich sage nicht, dass Google schuppig ist. Es gibt Fälle, in denen die Google-Kopie blockiert ist (anscheinend zum Beispiel im Iran).

Würde ich einen Timer einrichten und nach dem jQuery-Objekt suchen?

Was wäre die Gefahr, dass beide Kopien durchkommen?

Sie suchen nicht wirklich nach Antworten wie "Verwenden Sie einfach Google" oder "Verwenden Sie einfach Ihre eigenen". Ich verstehe diese Argumente. Ich verstehe auch, dass der Nutzer wahrscheinlich die Google-Version zwischengespeichert hat. Ich denke über Fallbacks für die Cloud im Allgemeinen nach.


Bearbeiten: Dieser Teil hinzugefügt ...

Da Google die Verwendung von google.load zum Laden der Ajax-Bibliotheken vorschlägt und nach Abschluss einen Rückruf ausführt, frage ich mich, ob dies der Schlüssel zur Serialisierung dieses Problems ist.

Ich weiß, es klingt ein bisschen verrückt. Ich versuche nur herauszufinden, ob dies zuverlässig möglich ist oder nicht.


Update: jQuery wird jetzt auf dem CDN von Microsoft gehostet.

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

Nosredna
quelle
9
Die erste Antwort lautete natürlich "Verwenden Sie nicht die von Google gehostete Version." :-)
Nosredna
7
Natürlich lag es daran, dass Sie sich nicht auf jemanden verlassen müssen, der Ihre Dateien hostet, wenn Sie eine seriöse Website hosten möchten.
Bryan Migliorisi
6
@ Bryan Migliorisi, ich denke Twitter ist doch nicht so ernst? Aber ich gebe zu, sie hatten ihre Probleme mit Google wie vor einem Monat, als Google ausfiel.
Ionuț G. Stan
18
Die Vorteile der Verwendung von Google oder nicht für das Hosting von JS lib sind würdig, wurden jedoch in mehreren anderen Threads erörtert. Ich suchte nach technischen Antworten bezüglich des JS-Fallbacks bei Ladeverzögerungen.
Nosredna
2
@ Joe Chung: Es wird wahrscheinlich auf dem System des Benutzers zwischengespeichert, was das Laden der Seite beschleunigt. Spart mir Bandbreite. Verwendet das CDN von Google. Etc.
Nosredna

Antworten:

810

Sie können es so erreichen:

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

Dies sollte in Ihrer Seite sein <head>und alle jQuery-fähigen Ereignishandler sollten in der sein <body>, um Fehler zu vermeiden (obwohl es nicht narrensicher ist!).

Ein weiterer Grund, von Google gehostete jQuery nicht zu verwenden, ist, dass in einigen Ländern der Domain-Name von Google verboten ist.

Rony
quelle
35
Blockieren Javascript-Downloads nicht bereits (synchron)? Mir scheint, das Problem der doppelten Kopie wäre daher kein Problem.
Matt Sherman
68
Javascript-Downloads sollten bereits synchron sein, wie Matt Sherman sagte. Andernfalls würden viele Probleme auftreten, wenn die Seite versuchte, ein Inline-Skript auszuführen, das auf einer Bibliothek beruhte, die nur zur Hälfte heruntergeladen wurde, oder wenn eine Bibliothekserweiterung ausgeführt wurde, ohne dass die Bibliothek vollständig heruntergeladen und ausgeführt wurde. Dies ist auch ein Grund, warum Yahoo YSlow empfiehlt, Javascript am Ende der Seiten zu platzieren. Damit wird das Herunterladen anderer Seitenelemente (einschließlich Stile und Bilder) nicht blockiert. Zumindest müsste der Browser die Ausführung verzögern, um nacheinander zu erfolgen.
Gapple
42
Kleine Korrektur von einem Validator-Fanatiker: Die Zeichenfolge '</' ist in JavaScript nicht zulässig, da sie möglicherweise als Ende des Skript-Tags (SGML-Kurz-Tag-Notation) falsch interpretiert wird. Führen Sie stattdessen '<' + '/ script>' aus. Prost,
Boldewyn
8
Dieses Beispiel funktioniert nicht. 1) Wenn die Google Ajax-Bibliothek nicht verfügbar ist, muss zuerst eine Zeitüberschreitung auftreten, bevor ein Fehler auftritt. Das kann eine Weile dauern. Bei meinem Test, meinen Computer vom Netzwerk zu trennen, hat er nur versucht und versucht und versucht und keine Zeitüberschreitung. 2) if (! JQuery) gibt einen Fehler aus, da jQuery nicht definiert ist und Javascript nicht weiß, was damit zu tun ist.
RedWolves
32
Um zu testen, ob jQuery geladen wurde, funktioniert (! Window.jQuery) einwandfrei und es wird die Art der Prüfung kurzgeschlossen.
Jörn Zaefferer
335

Der mit Abstand einfachste und sauberste Weg, dies zu tun:

<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>
BenjaminRH
quelle
1
@jpp nicht für XHTML 1.0undHTML 4.01
BenjaminRH
5
Die Leute bitten mich immer wieder, die type="text/javascript"Teile zu entfernen. Wenn Sie also HTML für ältere Browser schreiben, beachten Sie, dass Sie dies jetzt hinzufügen müssen.
BenjaminRH
6
@BenjaminRH: type="text/javascript"war auch in älteren Browsern nicht erforderlich , da alle standardmäßig Javascript verwendeten. Wirklich ältere Browser haben sich das languageAttribut angesehen. Aber selbst dann war Javascript die Standardeinstellung, wenn das Attribut fehlte.
Martijn
1
@ Martinijn Aber ich mochte das glänzende Validierungsabzeichen :)
BenjaminRH
3
@Trojan Absolut möglich, stapeln Sie einfach die Anrufe. Beachten Sie, dass Sie zu diesem Zeitpunkt neue Verbindungshosts öffnen, sodass das HTTP-Pipelining wahrscheinlich schneller ist. ... <script src="//cdn1.com/jquery.js"></script> <script>window.jQuery || document.write('<script src="//cdn2.com/jquery.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="local/jquery.js"><\/script>')</script>
Tom McKenzie
76

Das scheint bei mir zu funktionieren:

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

Die Funktionsweise besteht darin, das googleObjekt zu verwenden, das durch Aufrufen von http://www.google.com/jsapi auf das windowObjekt geladen wird . Wenn dieses Objekt nicht vorhanden ist, gehen wir davon aus, dass der Zugriff auf Google fehlschlägt. In diesem Fall laden wir eine lokale Kopie mit document.write. (In diesem Fall verwende ich meinen eigenen Server. Bitte verwenden Sie Ihren eigenen, um dies zu testen.)

Ich teste auch auf das Vorhandensein von window.google.load- ich könnte auch typeofüberprüfen, ob es sich bei den Dingen um Objekte oder Funktionen handelt. Aber ich denke, das macht den Trick.

Hier ist nur die Ladelogik, da die Code-Hervorhebung anscheinend fehlschlägt, da ich die gesamte HTML-Seite gepostet habe, die ich getestet habe:

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

Obwohl ich sagen muss, bin ich mir nicht sicher, ob Sie, wenn dies ein Problem für Ihre Website-Besucher ist, überhaupt mit der Google AJAX Libraries-API herumspielen sollten .

Unterhaltsame Tatsache : Ich habe anfangs versucht, in verschiedenen Versionen einen try..catch-Block dafür zu verwenden, konnte jedoch keine so saubere Kombination finden. Es würde mich interessieren, andere Implementierungen dieser Idee nur als Übung zu sehen.

artlung
quelle
1
Was ist der Vorteil der Verwendung von google.load in dieser Situation, anstatt ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js direkt zu laden, wie Rony vorgeschlagen hat? Ich denke, das Laden fängt auch Probleme mit entfernten Bibliotheken direkt auf (was ist, wenn Google JQuery 1.3.2 nicht mehr bereitstellt). Darüber hinaus bemerkt die Version von Rony Netzwerkprobleme, nachdem www.google.com/jsapi abgerufen wurde, insbesondere wenn jsapi aus dem Cache geladen wurde. Möglicherweise müssen Sie den Rückruf von google.load verwenden, um sicherzugehen (oder es gibt einen Rückgabewert, um google.load in if (..) aufzunehmen).
Arjan
Wenn man auf das Vorhandensein von Google.com testet, kann man einen Netzwerkanruf tätigen oder das Vorhandensein des "Gatekeeper" -Objekts überprüfen. Ich überprüfe das Google-Objekt und seine "Lade" -Funktion. Wenn beide fehlschlagen, kein Google, und ich brauche die lokale Version. In der Version von Rony wird die URL www.google.com/jsapi vollständig ignoriert. Daher bin ich mir nicht sicher, warum Sie angeben, dass sie abgerufen wurde.
Artlung
Am Ende muss nur die jquery-Bibliothek geladen werden. Eine Google-Bibliothek ist keine Voraussetzung. In Rony's Antwort weiß man sicher, ob das Laden von Google (oder dem Cache) erfolgreich war. Bei Ihrer Prüfung auf "if (window.google && window.google.load)" wird die jquery-Bibliothek jedoch immer noch nicht geladen. Das tatsächliche Laden der jquery-Bibliothek wird nicht überprüft?
Arjan
Ah, ich sehe, wie ich die Verwirrung verursacht habe. "Rony's Version bemerkt Netzwerkprobleme, nachdem www.google.com/jsapi abgerufen wurde" sollte besser lauten: "Ihre Version bemerkt keine Netzwerkprobleme, nachdem www.google.com/jsapi abgerufen wurde".
Arjan
2
Wir haben kürzlich auf Google als jQuery-Host umgestellt. Wenn wir Fehlerberichte von blockierten Benutzern erhalten, verwende ich eine Variante Ihrer Antwort, um unseren Client-Code zu überarbeiten. Gute Antwort!
Jarrod Dixon
30

Wenn Sie modernizr.js in Ihre Site eingebettet haben, können Sie Ihre Skripte mithilfe der integrierten Datei yepnope.js asynchron laden - unter anderem jQuery (mit 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();
    }
}]);

Dadurch wird jQuery von der Google-CDN geladen. Anschließend wird geprüft, ob jQuery erfolgreich geladen wurde. Wenn nicht ("nein"), wird die lokale Version geladen. Auch Ihre persönlichen Skripte werden geladen - das "beides" zeigt an, dass der Ladevorgang unabhängig vom Testergebnis eingeleitet wird.

Wenn alle Ladevorgänge abgeschlossen sind, wird eine Funktion ausgeführt, im Fall 'MyApp.init'.

Ich persönlich bevorzuge diese Art des asynchronen Skriptladens. Und da ich mich beim Erstellen einer Site auf die von modernizr bereitgestellten Funktionstests verlasse, habe ich sie trotzdem in die Site eingebettet. Es gibt also eigentlich keinen Overhead.

Emanuel Kluge
quelle
2
Ich denke, Sie verpassen den Punkt der Frage - wie würden Sie vorgehen, um das Moernizr-Skript von einem CDN zu laden?
George Filippakos
2
Ich kann das Laden von Modernizr von einem CDN nicht empfehlen. Man sollte lieber den kleinsten Custom Build von modernizr.com bekommen.
Emanuel Kluge
2
Diese Option erhält also +16 im Vergleich zu den 500/200 +, die die anderen Optionen erhalten. Das hört sich aber ganz gut an. Ist es einfach nicht beliebt, weil man sich auf Modernizer verlässt? Ich verwende Modernizer sowieso auf unserer Website. Wenn dies besser ist als die anderen Antworten, kann mich jemand darüber informieren? Ich bin ziemlich neu in JQuery, daher wird eine Klarstellung geschätzt.
Redfox05
2
Dies war zum Zeitpunkt der Antwort eine wirklich gute Option, ist jedoch ab 2015 yepnope.jsveraltet. siehe stackoverflow.com/questions/33986561/…
Obmerk Kronen
Modernizr wurde entwickelt, um Probleme wie diese Frage zu lösen. +1
Carlos Quijano
21

Hier gibt es einige großartige Lösungen, aber ich möchte in Bezug auf die lokale Datei noch einen Schritt weiter gehen.

In einem Szenario, in dem Google fehlschlägt, sollte eine lokale Quelle geladen werden, aber möglicherweise ist eine physische Datei auf dem Server nicht unbedingt die beste Option. Ich spreche dies an, weil ich derzeit dieselbe Lösung implementiere. Ich möchte jedoch nur auf eine lokale Datei zurückgreifen, die von einer Datenquelle generiert wird.

Meine Gründe dafür sind, dass ich ein wenig darüber nachdenken möchte, was ich von Google lade und was ich auf dem lokalen Server habe. Wenn ich Versionen ändern möchte, möchte ich meine lokale Kopie mit dem synchronisieren, was ich von Google laden möchte. In einer Umgebung mit vielen Entwicklern wäre es meiner Meinung nach am besten, diesen Prozess so zu automatisieren, dass lediglich eine Versionsnummer in einer Konfigurationsdatei geändert werden muss.

Hier ist meine vorgeschlagene Lösung, die theoretisch funktionieren sollte:

  • In einer Anwendungskonfigurationsdatei speichere ich drei Dinge: die absolute URL für die Bibliothek, die URL für die JavaScript-API und die Versionsnummer
  • Schreiben Sie eine Klasse, die den Dateiinhalt der Bibliothek selbst abruft (die URL aus der App-Konfiguration abruft) und in meiner Datenquelle mit dem Namen und der Versionsnummer speichert
  • Schreiben Sie einen Handler, der meine lokale Datei aus der Datenbank zieht und die Datei zwischenspeichert, bis sich die Versionsnummer ändert.
  • Wenn sich dies ändert (in meiner App-Konfiguration), ruft meine Klasse den Dateiinhalt basierend auf der Versionsnummer ab, speichert ihn als neuen Datensatz in meiner Datenquelle, und der Handler greift ein und stellt die neue Version bereit.

Wenn mein Code richtig geschrieben ist, müsste ich theoretisch nur die Versionsnummer in meiner App-Konfiguration ändern, dann Viola! Sie haben eine automatisierte Fallback-Lösung und müssen keine physischen Dateien auf Ihrem Server verwalten.

Was denken alle? Vielleicht ist dies ein Overkill, aber es könnte eine elegante Methode zur Pflege Ihrer AJAX-Bibliotheken sein.

Eichel

Eichel
quelle
Wenn Sie all diese Arbeiten nur für jQuery ausführen, würde ich sagen, dass dies übertrieben ist. Wenn Sie jedoch bereits einige dieser Komponenten für andere Teile Ihrer App installiert haben (z. B. wenn Sie bereits Skripte aus einer Datenbank laden), sieht es ziemlich gut aus.
Michael Haren
1
+1 für gründlich und neuartig, obwohl ich nicht überzeugt bin, dass der Nutzen die Entwicklungszeit und -komplexität rechtfertigt.
Cory House
20
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);

}

Nachdem Sie versucht haben, Googles Kopie aus dem CDN aufzunehmen.

In HTML5 müssen Sie das typeAttribut nicht festlegen .

Sie können auch ...

window.jQuery || document.write('<script src="/libs/jquery.js"><\/script>');
Alex
quelle
2
+1 sieht sauberer aus. Es gibt einen kleinen Tippfehler oben, den ich nicht löschen kann, da seine zwei kleinen Klammern nach 'undefined'
naveen
1
Erste Option vermeidet die Chrome-Warnung[Violation] Avoid using document.write().
Bob Stein
Die erste Option scheint leider nicht synchron zu laden . Zweite Option tut .
Bob Stein
10

Möglicherweise möchten Sie Ihre lokale Datei als letzten Ausweg verwenden.

Scheint, dass jQuerys eigenes CDN derzeit kein https unterstützt. Wenn ja, möchten Sie möglicherweise zuerst von dort laden.

Hier ist die Reihenfolge: Google CDN => Microsoft CDN => Ihre lokale Kopie.

<!-- 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> 
Edward Olamisan
quelle
Ist wirklich mehr als ein Fallback erforderlich? Wenn beide offline sind, wartet der Benutzer über eine Minute, bevor er Ihre Site sieht
George Filippakos
1
Es dauert nicht 1 Minute, bis ein Skript nicht geladen werden kann.
Edward Olamisan
@ geo1701 und Edward, es ist wirklich kein dritter nötig. Selbst ein Fallback muss sich noch als zuverlässig erweisen. Wenn die Google-API nicht verfügbar ist, habe ich noch keine Garantie dafür gesehen, dass der erste Versuch überhaupt fehlschlägt. Ich habe ein Fallszenario
hexalys
6

Laden Sie die neueste / ältere jQuery-Version und den Fallback unter bestimmten Bedingungen:

<!--[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]-->
Neiker
quelle
Dies ist nicht browserübergreifend kompatibel.
Josh Habdas
Josh, ja, das ist es.
Neiker
4

Hier ist eine großartige Erklärung dazu!

Implementiert auch Ladeverzögerungen und Timeouts!

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

Stuart.Sklinar
quelle
Nur-Link-Antworten sind nicht nützlich und werden als minderwertig angesehen. Kopieren Sie die relevanten Bits in Ihre Antwort, wobei Sie natürlich die Quelle angeben.
random_user_name
@cale_b Machst du Witze? Diese Antwort ist über 7 Jahre alt, daher ist ein solcher Kommentar nicht gerechtfertigt.
Stuart.Sklinar
Ja, das ist eine alte Antwort. Obwohl ihr Vorschlag gültig ist. Antworten, bei denen es sich lediglich um Links an anderer Stelle handelt, können gelöscht werden. Weiterer Leser: meta.stackoverflow.com/q/8259
Rob
Ich stimme vollkommen zu, ich würde selbst mit Vorschlägen moderieren - aber es ist sinnlos, es 7 Jahre später zu sagen. Es sollte vor 7 Jahren so moderiert worden sein, nicht 7 Jahre später.
Stuart.Sklinar
1
@ Stuart.Sklinar - wenn ich es vor 7 Jahren gesehen hätte, hätte ich es getan :) Ich fand mich hier wieder, um Nachforschungen anzustellen und dies zum ersten Mal zu sehen. Es tut mir leid, Sie zu frustrieren - ich denke, unsere Jobs bei SO sollen Verwalter der Website sein, was manchmal bedeutet, alte Fragen oder Antworten zu kommentieren, zu bearbeiten oder zu verbessern ...
random_user_name
4

Fügen Sie für Benutzer von ASP.NET MVC 5 diesen Code in Ihre BundleConfig.cs ein, um das CDN für jquery zu aktivieren:

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);
Muhammad Rehan Saeed
quelle
4

UPDATE:
Diese Antwort hat sich als falsch herausgestellt. Bitte beachten Sie die Kommentare für die wirkliche Erklärung.


Die meisten Ihrer Fragen wurden beantwortet, aber der letzte Teil:

Was wäre die Gefahr, dass beide Kopien durchkommen?

Eigentlich keine. Sie würden Bandbreite verschwenden, möglicherweise einige Millisekunden hinzufügen, um eine zweite nutzlose Kopie herunterzuladen, aber es schadet nicht wirklich, wenn beide durchkommen. Sie sollten dies natürlich mit den oben genannten Techniken vermeiden.

WhyNotHugo
quelle
5
Tatsächlich kann das zweimalige Laden von jQuery laut dieser Frage viele Probleme verursachen .
ShadowCat7
Warum testen Sie es nicht selbst und laden die jquery-Bibliothek zweimal manuell? dann wird die Antwort enthüllt.
luke_mclachlan
Warum genau ist es so falsch? @ ShadowCat7 Kannst du genauer auf die Probleme eingehen, die es verursacht? Das einzige Problem, das ich in der von Ihnen verlinkten Frage explizit sehe, ist das "Löschen aller zuvor geladenen Plugins". Das sollte aber nicht gelten, wenn dieselbe jQuery-Datei zweimal hintereinander geladen wird, oder? Ich frage, weil die anderen Lösungen für den lokalen Fallback hier so kompliziert sind und document.write an einigen Stellen als böse eingestuft wird .
Bob Stein
2

Ich habe eine Übersicht erstellt, die jQuery dynamisch laden soll, wenn es noch nicht geladen ist. Wenn die Quelle ausfällt, werden Fallbacks (aus vielen Antworten zusammengesetzt) fortgesetzt : https://gist.github.com/tigerhawkvok/9673154

Bitte beachten Sie, dass ich vorhabe, die Liste auf dem neuesten Stand zu halten, aber nicht diese Antwort, für das, was es wert ist!

/* 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();
}
Philip Kahn
quelle
2

Von Google gehostete jQuery

  • Wenn Sie sich für ältere Browser interessieren, hauptsächlich für IE-Versionen vor IE9, ist dies die am weitesten kompatible jQuery-Version
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  • Wenn Sie sich nicht für oldIE interessieren, ist dieses kleiner und schneller:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

Backup / Fallback Plan!

  • In beiden Fällen sollten Sie einen Fallback auf lokal verwenden, falls das Google CDN ausfällt (unwahrscheinlich) oder an einem Ort blockiert wird, von dem aus Ihre Nutzer (etwas wahrscheinlicher) auf Ihre Website zugreifen, z. B. im Iran oder manchmal in China.
<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>

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

Ryan
quelle
Beachten Sie, dass das Laden von Skripten über unsichere Protokolle einen XSS-Angriffsvektor öffnet.
Josh Habdas
2

Ich denke, dass das letzte <bis \ x3C in der Zeichenfolge entkommen sollte. Wenn der Browser dies sieht, betrachtet er dies als das Ende des Skriptblocks (da der HTML-Parser keine Ahnung von JavaScript hat, kann er nicht zwischen etwas unterscheiden, das nur in einer Zeichenfolge angezeigt wird, und etwas, das das Skript tatsächlich beenden soll Element). Das buchstäbliche Erscheinen in JavaScript innerhalb einer HTML-Seite führt (im besten Fall) zu Fehlern und (im schlimmsten Fall) zu einer großen Sicherheitslücke.

<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>
JKhuang
quelle
2
if (typeof jQuery == 'undefined')) { ...

Oder

if(!window.jQuery){

Funktioniert nicht, wenn die CDN-Version nicht geladen ist, da der Browser diese Bedingung durchläuft und währenddessen immer noch den Rest der Javascripts herunterlädt, die jQuery benötigen, und einen Fehler zurückgibt. Die Lösung bestand darin, Skripte über diese Bedingung zu laden.

    <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>
Mirek Komárek
quelle
Ich habe beim Testen von Skripten in Google Chrome ein Problem festgestellt: das Caching. Ersetzen Sie für lokale Tests einfach src im Abschnitt else durch etwas wie s.src = 'my_javascripts.js' + '?' + Math.floor (Math.random () * 10001);
Mirek Komárek
Alex 'Antwort funktioniert nicht, wenn die CDN-Version nicht geladen ist, da der Browser diese Bedingung durchläuft und währenddessen immer noch den Rest der Javascripts herunterlädt, für die eine Abfrage erforderlich ist, und einen Fehler zurückgibt. -> Heruntergeladene JavaScript-Dateien blockieren die Ausführung des nächsten Codes Es ist also kein Problem .
alex
2

Fast alle öffentlichen CDNs sind ziemlich zuverlässig. Wenn Sie sich jedoch Sorgen über blockierte Google-Domains machen, können Sie einfach auf ein alternatives jQuery-CDN zurückgreifen . In einem solchen Fall bevorzugen Sie jedoch möglicherweise die umgekehrte Vorgehensweise und verwenden ein anderes CDN als bevorzugte Option und greifen auf Google CDN zurück, um fehlgeschlagene Anforderungen und Wartezeiten zu vermeiden:

<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>
Hamid Sarfraz
quelle
1

Unter Verwendung der Razor-Syntax in ASP.NET bietet dieser Code Fallback-Unterstützung und arbeitet mit einem virtuellen Stammverzeichnis:

@{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>

Oder machen Sie einen Helfer ( Helferübersicht ):

@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>")
}

und benutze es so:

@CdnScript("jquery-1.7.1.min.js", "ajax/jQuery", "window.jQuery")
@CdnScript("jquery.validate.min.js", "ajax/jquery.validate/1.9", "jQuery.fn.validate")
Edward Brey
quelle
Ich habe nie ein Herz für Razor, aber es sieht aus wie ein Verschleierer, nur dass der Code dadurch eher länger als kürzer wird (er ist doppelt so lang wie dieser .
Maaartinus
@maaartinus: Das ist kein Vergleich von Äpfeln zu Äpfeln. Die Antwort von BenjaminRH, auf die Sie sich beziehen, bezieht sich auf ein einzelnes CDN-gehostetes Skript. Mit dem CdnScriptHelfer benötigen Sie nur eine Codezeile pro Skript . Je mehr Skripte Sie haben, desto höher ist die Auszahlung.
Edward Brey
Sicher ... es war nur ein Scherz. Ich denke jedoch, dass dies nicht der optimale Weg ist. Wenn etwas fehlschlägt, würde ich CDN vollständig ignorieren und für alle Skripte zum Fallback wechseln. Ich bin mir nicht sicher, ob dies machbar ist, da ich nicht weiß, wie das Laden genau funktioniert.
Maaartinus
@maaartinus: Da jeder CDN-Skriptladevorgang unabhängig fehlschlagen kann, müssen Sie jeden Ladevorgang separat überprüfen. Es gibt keine zuverlässige Methode für eine einzelne CDN-Prüfung, bei der alle Skripte von CDN im Vergleich zu lokal geladen werden.
Edward Brey
Der Fall, der mich beunruhigt, ist ein Ausfall der CDN-Site, der zu Wartezeiten für viele Ladevorgänge führt. Also hätte ich gerne so etwas try { for (Script s : ...) cdnLoad(s); } catch (...) { for (Script s : ...) ownLoad(s); }. Dies in ein paar ifs zu übersetzen, könnte ein Albtraum sein.
Maaartinus
1

Obwohl das Schreiben document.write("<script></script>")für jQuery-Backoff einfacher zu sein scheint, gibt Chrome in diesem Fall einen Validierungsfehler aus. Also ziehe ich es vor, "Skript" -Wort zu brechen. So wird es sicherer wie oben.

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

Bei langfristigen Problemen ist es besser, JQuery-Fallbacks zu protokollieren. Wenn im ersten Code das erste CDN nicht verfügbar ist, wird JQuery von einem anderen CDN geladen. Aber vielleicht möchten Sie dieses fehlerhafte CDN kennen und dauerhaft entfernen. (Dieser Fall ist ein sehr außergewöhnlicher Fall.) Es ist auch besser, Fallback-Probleme zu protokollieren. So können Sie mit AJAX fehlerhafte Fälle senden. Da JQuery nicht definiert ist, sollten Sie Vanille-Javascript für AJAX-Anforderungen verwenden.

<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>
trante
quelle
0

Ein weiterer Fallback, der ajax.googleapis.com durch ersetzt cdnjs.cloudflare.com ersetzt :

(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);
  • Sie können sich an eine jQuery-Version halten, indem Sie sie in der Zeichenfolge angeben
  • Perfekt für Asset Management, das nicht mit HTML-Snips funktioniert
  • In freier Wildbahn getestet - funktioniert perfekt für Benutzer aus China
Redaxmedia
quelle
Könnten Sie die folgende Aussage näher erläutern: "Sie müssen sich nicht um die jQuery-Version kümmern"?
Josh Habdas
Die Version ist Teil der URL, die von diesem Ansatz nicht berührt werden soll ... jquery / 3.xx / jquery.min.js
redaxmedia
1
Kann dies zu einem Bruch führen, wenn jQuery auf Version 4 wechselt und rückwärts inkompatible Änderungen einführt?
Josh Habdas
-1, da dies zu einem Bruch führen wird, wenn jQuery Änderungen einführt, die Ihre Skripte noch nicht unterstützen, es sei denn, die Version ist angegeben.
Lookaji
@lookaji Ich denke, Sie verstehen den Fallback nicht. Es ersetzt die Domain, in der es gehostet wird, und berührt NICHT den Dateinamen / die Version.
Redaxmedia
0

Sie können Code verwenden wie:

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

Es gibt aber auch Bibliotheken, mit denen Sie mehrere mögliche Fallbacks für Ihre Skripte einrichten und den Ladevorgang optimieren können:

  • Basket.js
  • RequireJS
  • Ja, nein

Beispiele:

korb.js Ich denke die beste Variante für jetzt. Wird Ihr Skript im localStorage zwischenspeichern, wodurch das nächste Laden beschleunigt wird. Der einfachste Anruf:

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

Dies gibt ein Versprechen zurück und Sie können den nächsten Fehleraufruf ausführen oder Abhängigkeiten vom Erfolg laden:

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

Ja, nein

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');
    }
  }
}]);
Роман Коптев
quelle