Meilleure façon d'utiliser le jquery hébergé de Google, mais repli sur Ma bibliothèque hébergée sur Google fail
quelle serait une bonne façon de tenter de charger le jquery hébergé chez Google (ou d'autres libs hébergés par Google), mais charger ma copie de jQuery si la tentative de Google échoue?
Je ne dis pas que Google est bizarre. Il y a des cas où la copie Google est bloquée (apparemment en Iran, par exemple).
est-ce que je mets en place une minuterie et je vérifie l'objet jQuery?
Quel serait le danger des deux copies à venir à travers?
pas vraiment à la recherche de réponses comme "il suffit D'utiliser Google one" ou "il suffit d'utiliser les vôtres."Je comprends ces arguments. Je comprends également que L'utilisateur est susceptible d'avoir la version de Google mise en cache. Je pense aux retombées pour le nuage en général.
Edit: Cette partie ajoutée...
puisque Google suggère d'utiliser google.charger pour charger les bibliothèques ajax, et il effectue un rappel lorsqu' c'est fait, je me demande si c'est la clé pour sérialiser ce problème.
je sais que ça semble un peu fou. J'essaie juste de savoir si ça peut être fait de manière fiable ou pas.
mise à jour: jQuery est maintenant hébergé sur le CDN de Microsoft.
21 réponses
Vous pouvez l'obtenir comme ceci:
<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>
cela devrait être dans votre page <head>
et tout jQuery ready event handler devrait être dans le <body>
pour éviter les erreurs (bien que ce ne soit pas infaillible!).
une raison de plus pour et non d'utiliser jQuery hébergé par Google est que dans certains pays, le nom de domaine de Google est interdit.
la façon la plus facile et la plus propre de le faire de loin:
<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>
Cela semble fonctionner pour moi:
<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>
la façon dont il fonctionne est d'utiliser le google
objet qui appelle http://www.google.com/jsapi charge sur l'objet window
. Si cet objet n'est pas présent, nous supposons que L'accès à Google est en panne. Si c'est le cas, nous chargeons une copie locale en utilisant document.write
. (j'utilise mon propre serveur dans ce cas, veuillez utiliser votre propre pour les tests).
je teste aussi la présence de window.google.load
- je peux aussi faire une vérification de typeof
pour voir que les choses sont des objets ou des fonctions selon le cas. Mais je pense que cela fait l'affaire.
Voici juste la logique de chargement, puisque la mise en évidence du code semble échouer puisque j'ai posté toute la page HTML que j'étais en train de tester:
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>');
}
bien que je dois dire, Je ne suis pas sûr que si c'est une préoccupation pour les visiteurs de votre site, vous devriez être bidon avec le Google AJAX bibliothèques API à tous.
fait Amusant : j'ai essayé d'abord d'utiliser un essai..bloc catch pour cela dans diverses versions mais n'a pas pu trouver une combinaison qui était aussi propre que cela. Je serais intéressé de voir d'autres implémentations de cette idée, purement comme un exercice.
si vous avez modernizr.js intégré sur votre site, vous pouvez utiliser le haut-yepnope.js pour charger vos scripts de manière asynchrone - entre autres jQuery (avec repli).
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();
}
}]);
cette charge jQuery de la part de Google-cdn. Ensuite, il est vérifié, si jQuery a été chargé avec succès. Si ce n'est pas le cas ("non"), la version locale est chargée. Aussi vos scripts personnels sont chargés - les "deux" indique que la charge processus est iniated indépendamment du résultat du test.
lorsque tous les processus de charge sont terminés, une fonction est exécutée, dans le cas 'MyApp.init'.
personnellement, je préfère cette façon de charger des scripts asynchrones. Et comme je m'appuie sur les fonctionnalités-tests fournis par modernizr lors de la construction d'un site, je l'ai intégré sur le site de toute façon. Donc il n'y a effectivement pas de frais généraux.
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);
}
après que vous ayez essayé d'inclure la copie de Google du CDN.
dans HTML5, vous n'avez pas besoin de définir l'attribut type
.
Vous pouvez également utiliser...
window.jQuery || document.write('<script src="/libs/jquery.js"><\/script>');
il y a de grandes solutions ici, mais j'aimerais aller un peu plus loin en ce qui concerne le fichier local.
dans un scénario où Google ne fonctionne pas, il devrait charger une source locale, mais peut-être un fichier physique sur le serveur n'est pas nécessairement la meilleure option. Je soulève cela parce que je suis en train de mettre en œuvre la même solution, seulement je veux revenir à un fichier local qui est généré par une source de données.
Mes raisons pour cela est que je veux pour avoir une certaine part d'esprit quand il s'agit de garder une trace de ce que je charge de Google par rapport à ce que j'ai sur le serveur local. Si je veux changer les versions, je veux garder ma copie locale synchronisée avec ce que J'essaie de charger à partir de Google. Dans un environnement où il y a beaucoup de développeurs, je pense que la meilleure approche serait d'automatiser ce processus de sorte que tout ce qu'on aurait à faire est de changer un numéro de version dans un fichier de configuration.
voici ma solution proposée qui devrait travail en théorie:
- dans un fichier de configuration d'application, je stocke 3 choses: L'URL absolue pour la bibliothèque, L'URL pour L'API JavaScript, et le numéro de version
- écrire une classe qui obtient le contenu du fichier de la bibliothèque elle-même (obtient L'URL de l'application config), le stocke dans ma source de données avec le nom et le numéro de version
- Écrire un handler qui sort mon fichier local de la base de données et le cache jusqu'à ce que le le numéro de version change.
- si elle change (dans ma configuration d'application), ma classe va tirer le contenu du fichier basé sur le numéro de version, enregistrer comme un nouvel enregistrement dans ma source de données, puis le gestionnaire va donner un coup de pied et servir la nouvelle version.
en théorie, si mon code est écrit correctement, tout ce que je dois faire est de changer le numéro de version dans ma config app puis viola! Vous avez une solution de rechange qui est automatisée, et vous n'avez pas à maintenez les fichiers physiques sur votre serveur.
Qu'en pense tout le monde? Peut-être que c'est exagéré, mais ça pourrait être une méthode élégante pour maintenir vos bibliothèques AJAX.
Gland
vous pourriez vouloir utiliser votre fichier local en dernier recours.
semble à présent que le CDN de jQuery ne supporte pas les https. Si c'est le cas, vous voudrez peut-être Charger à partir de là en premier.
donc voici la séquence: Google CDN => Microsoft CDN => Votre copie 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>
chargement conditionnel de la dernière version de jQuery / legacy et repli:
<!--[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]-->
- Étape 1: est-ce que jQuery n'a pas chargé? (cocher
jQuery
variable)
Comment vérifier une variable non définie en JavaScript
- Étape 2: Importer dynamiquement (la sauvegarde) le fichier javascript
Comment puis-je inclure un fichier JavaScript dans un autre fichier JavaScript?
en raison du problème de bannissement de Google, je préfère utiliser le cdn de Microsoft http://www.asp.net/ajaxlibrary/cdn.ashx
Voici une grande explication à ce sujet!
implémente également les délais de chargement et les temps morts!
http://happyworm.com/blog/2010/01/28/a-simple-and-robust-cdn-failover-for-jquery-14-in-one-line /
pour les personnes utilisant ASP.NET MVC 5, ajoutez ce code dans votre BundleConfig.cs pour activer le CDN pour 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);
mise à jour:
Cette réponse s'est avéré être faux. Veuillez voir les commentaires de la vraie explication.
la plupart d'entre vous question a été répondu, mais pour la dernière partie:
quel serait le danger que les deux copies passent?
pas vraiment. Vous gaspilleriez de la bande passante, vous pourriez ajouter quelques millisecondes de téléchargement une deuxième copie inutile, mais il n'y a pas de mal s'ils arrivent tous les deux. Vous devriez, bien sûr, d'éviter cela en utilisant les techniques mentionnées ci-dessus.
Google Hébergé jQuery
- si vous vous souciez des navigateurs plus anciens, principalement les versions D'IE antérieures à IE9, c'est la version jQuery la plus compatible
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
- si vous ne vous souciez pas de l'oldIE, celui-ci est plus petit et plus rapide:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
Plan De Secours!
- Dans tous les cas, vous devriez utiliser un repli sur local juste au cas où le CDN Google échoue (peu probable) ou est bloqué dans un endroit que vos utilisateurs accèdent à votre site à partir (légèrement plus probable), comme L'Iran ou parfois la Chine.
<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>
référence: http://websitespeedoptimizations.com/ContentDeliveryNetworkPost.aspx
je considère que devrait échapper à la dernière < to \x3C dans string. Quand le navigateur voit, il considère que c'est la fin du bloc script (puisque L'analyseur HTML n'a aucune idée de JavaScript, il ne peut pas faire de distinction entre quelque chose qui apparaît juste dans une chaîne de caractères et quelque chose qui est en fait destiné à mettre fin à l'élément script). Donc apparaître littéralement dans JavaScript qui est à l'intérieur d'une page HTML va (dans le meilleur des cas) causer des erreurs, et (dans le pire des cas) être un énorme trou de sécurité.
<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')) { ...
ou
if(!window.jQuery){
ne fonctionnera pas si la version cdn n'est pas chargée, parce que le navigateur va courir à travers cette condition et pendant qu'il télécharge encore le reste des javascripts qui a besoin de jQuery et il retourne l'erreur. La Solution était de charger les scripts dans cette condition.
<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>
utilisant la syntaxe Razor dans ASP.NET, ce code fournit un support de repli et fonctionne avec une racine virtuelle:
@{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>
Ou faire un helper ( helper "vue d'ensemble de 151970920" ):
@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>")
}
et l'utiliser comme ceci:
@CdnScript("jquery-1.7.1.min.js", "ajax/jQuery", "window.jQuery")
@CdnScript("jquery.validate.min.js", "ajax/jquery.validate/1.9", "jQuery.fn.validate")
j'ai fait un Gist qui devrait charger dynamiquement jQuery si elle n'est pas déjà chargée, et si la source échoue, il procède sur les retombées (cousu ensemble à partir de nombreuses réponses): https://gist.github.com/tigerhawkvok/9673154
Veuillez noter que j'ai l'intention de garder l'Essentiel à jour, mais pas cette réponse, pour ce que ça vaut!
/* 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();
}
bien que l'écriture de document.write("<script></script>")
semble plus facile pour jQuery backoff, Chrome donne une erreur de validation sur ce cas. Donc je préfère casser le mot "script". Donc il devient plus sûr comme ci-dessus.
<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>
pour les questions à long terme, il serait préférable d'enregistrer les retombées de JQuery. Dans le code ci-dessus, si le premier CDN N'est pas disponible, JQuery est chargé à partir d'un autre CDN. Mais vous pourriez vouloir savoir que CDN erroné et l'enlever de façon permanente. (ce cas est très exceptionnels cas) Aussi il est préférable d'enregistrer les problèmes de repli. Donc vous pouvez envoyer des cas erronés avec AJAX. En raison de JQuery n'est pas défini, vous devriez utiliser le javascript vanille pour les requêtes 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é de charger la ressource à partir d'une mémoire externe de données au-delà de votre contrôle est difficile. Rechercher des fonctions manquantes est totalement fallacieux comme un moyen d'éviter de souffrir un temps d'arrêt, comme décrit ci-dessous: http://www.tech-101.com/support/topic/4499-issues-using-a-cdn/
encore un autre repli qui remplace ajax.googleapis.com avec 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);
- vous pouvez vous en tenir à une version jQuery en la spécifiant dans la chaîne
- Parfait pour la Gestion des Actifs qui ne fonctionne pas avec le HTML, les cisailles
- testé dans la nature-fonctionne parfait pour les utilisateurs de la Chine