web-dev-qa-db-fra.com

La meilleure façon d'utiliser le jQuery hébergé de Google, mais de revenir à ma bibliothèque hébergée sur Google

Quel serait un bon moyen d'essayer de charger le jQuery hébergé chez Google (ou une autre bibliothèque hébergée de Google), mais de charger ma copie de jQuery si la tentative de Google échoue?

Je ne dis pas que Google est floconneux. Il existe des cas où la copie de Google est bloquée (apparemment en Iran, par exemple).

Aurais-je configurer une minuterie et vérifier l'objet jQuery?

Quel serait le danger de voir les deux copies passer?

Pas vraiment à la recherche de réponses telles que "utilisez simplement Google" ou "utilisez simplement les vôtres". Je comprends ces arguments. Je comprends également que l'utilisateur est susceptible de mettre la version de Google en cache. Je pense aux solutions de rechange pour le cloud en général.


Edit: Cette partie a été ajoutée ...

Étant donné que Google suggère d'utiliser google.load pour charger les bibliothèques ajax et qu'il effectue un rappel à la fin de l'opération, je me demande si c'est la clé pour sérialiser ce problème.

Je sais que cela semble un peu fou. J'essaie simplement de savoir si cela peut être fait de manière fiable ou non.


Mise à jour: jQuery est maintenant hébergé sur le CDN de Microsoft.

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

1001
Nosredna

Vous pouvez y arriver comme ça:

<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 le <head> de votre page et tous les gestionnaires d'événements prêts pour jQuery devraient être dans le <body> pour éviter les erreurs (bien que ce ne soit pas infaillible!.

Une autre raison de non utiliser jQuery hébergé par Google est que, dans certains pays, le nom de domaine de Google est banni.

793
Rony

Le moyen le plus simple et le plus propre de le faire, et 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>
333
BenjaminRH

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 cela fonctionne consiste à utiliser l'objet google que l'appelant http://www.google.com/jsapi charge dans l'objet window. Si cet objet n'est pas présent, nous supposons que l'accès à Google échoue. Si tel est le cas, nous chargeons une copie locale à l'aide de document.write. (J'utilise mon propre serveur dans ce cas, veuillez utiliser votre propre serveur pour le tester).

Je vérifie également la présence de window.google.load. Je pourrais également effectuer une vérification typeof pour vérifier que les objets sont des objets ou des fonctions appropriés. Mais je pense que cela fait l'affaire.

Voici juste la logique de chargement, car la mise en surbrillance du code semble échouer puisque j'ai posté toute la page HTML que je testais:

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 cela concerne les visiteurs de votre site, vous devriez manipuler la Google AJAX API de bibliothèques du tout.

Fun fact: J'ai d'abord essayé d'utiliser un bloc try..catch pour cela dans différentes versions, mais je n'ai pas trouvé de combinaison aussi nette que celle-ci. Je serais intéressé de voir d'autres implémentations de cette idée, purement comme un exercice.

75
artlung

Si vous avez modernizr.js intégré sur votre site, vous pouvez utiliser le fichier yepnope.js intégré pour charger vos scripts de manière asynchrone, notamment 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();
    }
}]);

Cela charge jQuery à partir de Google-cdn. Ensuite, il est vérifié si jQuery a été chargé avec succès. Si ce n'est pas le cas ("nope"), la version locale est chargée. De plus, vos scripts personnels sont chargés - le "deux" indique que le processus de chargement est démarré indépendamment du résultat du test.

Lorsque tous les processus de chargement sont terminés, une fonction est exécutée, dans le cas «MyApp.init».

Personnellement, je préfère cette méthode de chargement de script asynchrone. Et comme je me base sur les tests de fonctionnalités fournis par modernizr lors de la construction d’un site, je l’ai néanmoins intégré au site. Donc, il n'y a pas de frais généraux.

30
Emanuel Kluge

Il y a quelques bonnes solutions ici, mais je voudrais aller un peu plus loin en ce qui concerne le fichier local.

Si Google échoue, il doit charger une source locale, mais un fichier physique sur le serveur n'est peut-être pas la meilleure option. Je soulève cette question parce que je suis en train de mettre en œuvre la même solution. Je souhaite seulement revenir à un fichier local généré par une source de données.

Cela tient à ce que je veux avoir l’esprit en tête pour garder une trace de ce que je charge sur Google par rapport à ce que j’ai sur le serveur local. Si je veux changer de version, je veux que ma copie locale soit synchronisée avec ce que je tente de charger depuis Google. Dans un environnement où il y a de nombreux développeurs, je pense que la meilleure approche serait d'automatiser ce processus afin qu'il ne reste plus qu'à changer le numéro de version d'un fichier de configuration.

Voici ma solution proposée qui devrait fonctionner en théorie:

  • Dans un fichier de configuration d'application, je vais stocker 3 éléments: l'URL absolue de la bibliothèque, l'URL de l'API JavaScript et le numéro de version.
  • Écrivez une classe qui récupère 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.
  • Ecrivez un gestionnaire qui extrait mon fichier local de la base de données et le met en cache jusqu'à ce que le numéro de version change.
  • Si cela change (dans ma configuration d'application), ma classe extraira le contenu du fichier en fonction du numéro de version, l'enregistrera en tant que nouvel enregistrement dans ma source de données, puis le gestionnaire démarrera et diffusera la nouvelle version.

En théorie, si mon code est écrit correctement, tout ce que je devrais faire est de changer le numéro de version dans la configuration de mon application, puis alto! Vous disposez d'une solution de secours automatisée et vous n'avez pas besoin de conserver des fichiers physiques sur votre serveur.

Qu'est-ce que tout le monde pense? C'est peut-être excessif, mais cela pourrait être une méthode élégante pour maintenir vos bibliothèques AJAX.

Gland

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

}

Après avoir tenté d'inclure la copie de Google à partir du CDN.

En HTML5, il n'est pas nécessaire de définir l'attribut type.

Vous pouvez aussi utiliser...

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

Vous voudrez peut-être utiliser votre fichier local en dernier recours.

Il semble que dès maintenant, le propre CDN de jQuery ne prend pas en charge https. Si c'est le cas, vous voudrez peut-être charger à partir de là en premier.

Voici donc 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> 
9
Edward Olamisan

Charge conditionnellement la dernière version de jQuery/ancienne version 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]-->
6
neiker

En raison du problème d'interdiction de Google, je préfère utiliser le cdn de Microsoft http://www.asp.net/ajaxlibrary/cdn.ashx

5
Serdar
  • Étape 1: Le chargement de jQuery a-t-il échoué? (cochez la variable jQuery)

Comment vérifier une variable non définie en JavaScript

  • Étape 2: Importer dynamiquement (le fichier de sauvegarde) le fichier javascript

Comment inclure un fichier JavaScript dans un autre fichier JavaScript?

5
ninjagecko

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

METTRE À JOUR:
Cette réponse s’est avérée fausse. S'il vous plaît voir les commentaires pour la vraie explication.


La plupart de vos questions ont reçu une réponse, mais en ce qui concerne la dernière partie:

Quel serait le danger de voir les deux copies passer?

Aucun vraiment. Vous gaspilleriez de la bande passante, vous pourriez ajouter quelques millisecondes au téléchargement d’une seconde copie inutile, mais vous ne risquez aucun préjudice si elles sont toutes deux transmises. Évidemment, vous devriez éviter cela en utilisant les techniques mentionnées ci-dessus.

4
WhyNotHugo

Voici une excellente explication à ce sujet!

Met également en œuvre les délais de chargement et les délais d'attente!

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

4
Stuart.Sklinar

J'ai créé un Gist qui devrait charger dynamiquement jQuery s'il n'est pas déjà chargé et, si le code source échoue, il effectue des replis (assemblés à partir de nombreuses réponses): https://Gist.github.com/tigerhawkvok/9673154

Veuillez noter que je prévois de garder Gist à 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();
}
2
Philip Kahn

Je considère que cela devrait échapper le dernier <to\x3C de la chaîne. Lorsque le navigateur le voit, il considère qu'il s'agit de la fin du bloc de script (dans la mesure où l'analyseur HTML n'a aucune idée de JavaScript, il ne peut pas distinguer ce qui apparaît simplement dans une chaîne de caractères et ce qui est censé mettre fin au script. élément). Ainsi, l'affichage littéral en JavaScript dans une page HTML provoquera (dans le meilleur des cas) des erreurs et (dans le pire des cas) une énorme faille 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>
2
JKhuang

Google hébergé jQuery

  • Si vous vous souciez des anciens navigateurs, principalement des versions de IE antérieures à IE9, il s'agit de 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 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 sauvegarde/de secours!

  • Dans les deux cas, vous devez utiliser une solution de secours locale si le CDN de Google échoue (peu probable) ou est bloqué dans un emplacement où vos utilisateurs accèdent à votre site (légèrement plus probable), comme en Iran ou parfois en 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

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

Ou

if(!window.jQuery){

Ne fonctionnera pas si la version cdn n'est pas chargée, car le navigateur exécute cette condition et continue de télécharger le reste des javascripts qui nécessitent jQuery et renvoie une erreur. La solution consistait à charger des scripts via 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>
2
Mirek Komárek

Bien que l'écriture de document.write("<script></script>") semble plus facile pour le retrait de jQuery, Chrome génère une erreur de validation sur ce cas. Donc, je préfère casser "script" Word. 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 problèmes à long terme, il serait préférable d’enregistrer les replis JQuery. Dans le code ci-dessus, si le premier CDN n'est pas disponible, JQuery est chargé à partir d'un autre CDN. Mais vous voudrez peut-être connaître ce CDN erroné et le supprimer définitivement. (Ce cas est un cas très exceptionnel) Il est également préférable de consigner les problèmes de repli. Vous pouvez donc envoyer des cas erronés avec AJAX. Comme JQuery n’est pas défini, vous devez utiliser Vanilla javascript pour la demande 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>
1
trante

L'impossibilité de charger la ressource à partir d'un magasin de données externe hors de votre contrôle est difficile. Rechercher des fonctions manquantes est totalement fallacieux pour éviter de perdre du temps, comme décrit ici: http://www.tech-101.com/support/topic/4499-issues-using-a-cdn/

1
jobeard

Utilisant la syntaxe Razor dans ASP.NET, ce code fournit un support de secours 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 faites un assistant ( helper overview ):

@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 ça:

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

Vous pouvez utiliser un code comme:

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

Mais il existe aussi des bibliothèques que vous pouvez utiliser pour configurer plusieurs solutions de secours possibles pour vos scripts et optimiser le processus de chargement:

  • basket.js
  • RequireJS
  • yepnope

Exemples:

basket.js Je pense que la meilleure variante pour le moment. Cachera votre script dans le stockage local, ce qui accélérera les prochains chargements. L'appel le plus simple:

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

Cela retournera une promesse et vous pourrez faire le prochain appel en cas d'erreur ou charger des dépendances en cas de succès:

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

Encore une autre solution de rechange 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 de jQuery en la spécifiant dans la chaîne
  • Parfait pour la gestion d'actifs qui ne fonctionne pas avec les fragments HTML
  • Testé à l'état sauvage - fonctionne parfaitement pour les utilisateurs de Chine
0
redaxmedia

Presque tous les CDN publics sont assez fiables. Toutefois, si vous craignez que le domaine Google ne soit bloqué, vous pouvez simplement recourir à une alternative jQuery CDN . Cependant, dans un tel cas, vous préférerez peut-être le faire de manière opposée et utiliser un autre CDN comme option de votre choix. Vous aurez alors recours à Google CDN pour éviter les échecs. demandes et temps d'attente:

<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>
0
Hamid Sarfraz