Was wäre ein guter Weg, um zu versuchen, die gehostete jQuery bei Google (oder eine andere von Google gehostete Bibliothek) zu laden, aber ich möchte meine Kopie von jQuery laden, wenn der Google-Versuch fehlschlägt?
Ich sage nicht, dass Google flockig ist. Es gibt Fälle, in denen die Google-Kopie gesperrt ist (beispielsweise im Iran).
Würde ich einen Timer einrichten und nach dem jQuery-Objekt suchen?
Was wäre die Gefahr, dass beide Exemplare durchkommen?
Nicht wirklich auf der Suche nach Antworten wie "einfach Google verwenden" oder "einfach nur eigene". Ich verstehe diese Argumente. Ich verstehe auch, dass die Google-Version für den Nutzer wahrscheinlich zwischengespeichert wird. Ich denke an Rückfälle für die Cloud im Allgemeinen.
Bearbeiten: Dieser Teil hinzugefügt ...
Da Google die Verwendung von google.load zum Laden der ajax-Bibliotheken vorschlägt und wenn dies ausgeführt wird, frage ich mich, ob dies der Schlüssel zum Serialisieren dieses Problems ist.
Ich weiß, es klingt ein bisschen verrückt. Ich versuche nur herauszufinden, ob dies auf zuverlässige Art und Weise möglich ist oder nicht.
Update: jQuery jetzt auf Microsoft CDN gehostet.
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 <head>
Ihrer Seite enthalten sein, und alle jQuery-fähigen Event-Handler sollten in <body>
enthalten sein, um Fehler zu vermeiden (obwohl dies nicht absolut sicher ist!).
Ein Grund mehr, nicht von Google gehostete jQuery zu verwenden, ist, dass in einigen Ländern der Domainname von Google verboten ist.
Der einfachste und sauberste Weg, dies bei weitem 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>
Das scheint für mich 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 google
-Objekt zu verwenden, das beim Aufruf von http://www.google.com/jsapi in das window
-Objekt 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
. (Ich verwende in diesem Fall 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 eine typeof
-Überprüfung durchführen, um zu sehen, ob Dinge Objekte oder Funktionen sind, die als geeignet gelten. Aber ich denke, das macht den Trick.
Hier ist nur die Ladelogik, da das Hervorheben von Code anscheinend fehlschlägt, seit 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 Anliegen für Ihre Website-Besucher ist, überhaupt mit der Google AJAX - Bibliotheken-API spielen sollten.
Fun fact: Ich habe in verschiedenen Versionen zunächst versucht, einen try..catch-Block zu verwenden, konnte aber keine so saubere Kombination finden.) Idee, nur als Übung.
Wenn Sie modernizr.js in Ihre Site eingebettet haben, können Sie die eingebauten yepnope.js verwenden, um Ihre Skripts asynchron zu 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();
}
}]);
Dies lädt jQuery vom Google-CDN. Anschließend wird geprüft, ob jQuery erfolgreich geladen wurde. Wenn nicht ("nope"), wird die lokale Version geladen. Auch Ihre persönlichen Skripte werden geladen - das "Beide" zeigt an, dass der Ladeprozess unabhängig vom Testergebnis initiiert wird.
Wenn alle Ladeprozesse 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 Feature-Tests von modernizr stütze, habe ich sie trotzdem in die Site eingebettet. Es gibt also eigentlich keinen Overhead.
Es gibt hier einige großartige Lösungen, aber ich möchte noch einen Schritt weiter gehen, wenn es um die lokale Datei geht.
In einem Szenario, in dem Google fehlschlägt, sollte eine lokale Quelle geladen werden. Möglicherweise ist jedoch eine physische Datei auf dem Server nicht unbedingt die beste Option. Ich spreche das an, weil ich derzeit dieselbe Lösung implementiere. Ich möchte nur auf eine lokale Datei zurückgreifen, die von einer Datenquelle generiert wird.
Meine Gründe dafür sind, dass ich etwas Verstand haben möchte, wenn es darum geht, zu verfolgen, was ich von Google geladen habe, oder was ich auf dem lokalen Server habe. Wenn ich die Version ändern möchte, möchte ich meine lokale Kopie mit dem, was ich von Google laden möchte, synchronisieren. In einer Umgebung, in der es viele Entwickler gibt, denke ich, der beste Ansatz wäre, diesen Prozess zu automatisieren, sodass nur eine Versionsnummer in einer Konfigurationsdatei geändert werden muss.
Hier ist meine vorgeschlagene Lösung, die theoretisch funktionieren sollte:
Theoretisch müsste ich, wenn mein Code richtig geschrieben ist, nur die Versionsnummer in meiner App-Konfiguration und dann die Viola ändern! Sie haben eine Fallback-Lösung, die automatisiert ist, und Sie müssen keine physischen Dateien auf Ihrem Server verwalten.
Was denken alle? Vielleicht ist das ein Overkill, aber es könnte eine elegante Methode sein, Ihre AJAX - Bibliotheken zu verwalten.
Eichel
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, die Kopie von Google aus dem CDN aufzunehmen.
In HTML5 müssen Sie das type
-Attribut nicht festlegen.
Sie können auch verwenden ...
window.jQuery || document.write('<script src="/libs/jquery.js"><\/script>');
Möglicherweise möchten Sie Ihre lokale Datei als letzten Ausweg verwenden.
Anscheinend unterstützt das eigene CDN von jQuery kein https. Wenn ja, dann möchten Sie vielleicht zuerst von dort laden.
Also hier 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>
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]-->
Wegen des Google-Verbotsproblems ziehe ich es vor, Microsofts cdn http://www.asp.net/ajaxlibrary/cdn.ashx zu verwenden.
jQuery
)So prüfen Sie eine nicht definierte Variable in JavaScript
Wie füge ich eine JavaScript-Datei in einer anderen JavaScript-Datei ein?
Für diejenigen, die ASP.NET MVC 5 verwenden, fügen Sie diesen Code in BundleConfig.cs hinzu, 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);
UPDATE:
Diese Antwort erwies sich als falsch. In den Kommentaren finden Sie die eigentliche Erklärung.
Die meisten von Ihnen wurden auf die Frage beantwortet, aber zum letzten Teil:
Was wäre die Gefahr, dass beide Exemplare durchkommen?
Wirklich nicht. Sie würden Bandbreite verschwenden und möglicherweise einige Millisekunden hinzufügen, wenn Sie eine zweite, nutzlose Kopie herunterladen. Es ist jedoch kein Schaden, wenn beide durchkommen. Sie sollten dies natürlich mit den oben genannten Techniken vermeiden.
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/
Ich habe eine Gist erstellt, die jQuery dynamisch laden sollte, wenn es nicht bereits geladen ist, und wenn die Quelle fehlschlägt, wird mit Fallbacks fortgefahren (aus vielen Antworten zusammengefügt): https://Gist.github.com/tigerhawkvok/9673154
Bitte beachte, dass ich vorhabe, den Gist auf dem neuesten Stand zu halten, aber nicht diese Antwort, 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();
}
Ich denke, dass das letzte <nach\x3C in String entgehen sollte. Wenn der Browser dies erkennt, sieht er dies als das Ende des Skriptblocks an (da der HTML-Parser keine Ahnung von JavaScript hat, kann er nicht zwischen etwas unterscheiden, das gerade in einem String angezeigt wird, und etwas, das das Skript eigentlich beenden soll Element). Wenn Sie also in JavaScript wörtlich in einer HTML-Seite erscheinen, wird dies (im besten Fall) Fehler verursachen und (im schlimmsten Fall) eine große Sicherheitslücke sein.
<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>
Google gehostete jQuery
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
Backup/Fallback-Plan!
<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>
Reference:http://websitespeedoptimizations.com/ContentDeliveryNetworkPost.aspx
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 der Rest der Javascripts, für die jQuery erforderlich ist, weiterhin heruntergeladen wird und der Fehler zurückgegeben wird. Die Lösung bestand darin, Skripts durch 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>
Obwohl das Schreiben von document.write("<script></script>")
für jQuery backoff einfacher erscheint, gibt Chrome in diesem Fall einen Überprüfungsfehler. Also ziehe ich es vor, "Script" Word 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>
Für langfristige Probleme ist es besser, JQuery-Fallbacks zu protokollieren. Wenn im ersten Code kein erstes CDN verfügbar ist, wird JQuery von einem anderen CDN geladen. Aber Sie könnten dieses fehlerhafte CDN wissen wollen und es dauerhaft entfernen. (Dieser Fall ist ein Ausnahmefall) Es ist auch besser, Fallback-Probleme zu protokollieren. So können Sie mit AJAX fehlerhafte Fälle versenden. Da JQuery nicht definiert ist, sollten Sie Vanilla-Javascript für die Anforderung von AJAX 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>
Es ist schwierig, die Ressource von einem externen Datenspeicher zu laden, auf den Sie keinen Einfluss haben. Das Suchen nach fehlenden Funktionen ist völlig trügerisch, um eine Zeitüberschreitung zu vermeiden, wie hier beschrieben: http://www.tech-101.com/support/topic/4499-issues-using-a-cdn/
Mit der Razor-Syntax in ASP.NET bietet dieser Code Unterstützung für die Unterstützung von Fallbacks.
@{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 ( Helper-Ü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")
Sie können Code wie folgt verwenden:
<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:
Beispiele:
basket.js Ich denke die beste Variante für jetzt. Zwischenspeichert Ihr Skript im localStorage, wodurch die nächsten Ladezeiten beschleunigt werden. Der einfachste Anruf:
basket.require({ url: '/path/to/jquery.js' });
Dadurch wird ein Versprechen zurückgegeben, und Sie können bei einem Fehler den nächsten Aufruf ausführen oder bei Erfolg Abhängigkeiten 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 ($) {
});
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');
}
}
}]);
Ein weiterer Fallback, der ajax.googleapis.com durch 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);
Fast alle öffentlichen CDNs sind ziemlich zuverlässig. Wenn Sie sich jedoch Sorgen über eine blockierte Google-Domain machen, können Sie einfach auf eine alternative jQuery-CDN zurückgreifen. In diesem Fall bevorzugen Sie jedoch möglicherweise die umgekehrte Vorgehensweise und verwenden eine andere CDN als bevorzugte Option und greifen auf Google CDN zurück, um Fehlschläge zu vermeiden Anfragen und Wartezeiten:
<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>