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

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

Question

Quel serait un bon moyen de charger le jQuery hébergé chez Google (ou autres bibliothèques hébergées sur Google), mais chargez 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).

Est-ce que je configurerais une minuterie et rechercherais l'objet jQuery?

Quel serait le danger de voir passer les deux copies?

Vous ne recherchez pas vraiment des réponses telles que & "; utilisez simplement celui de Google &"; ou & "utilisez simplement le vôtre. &"; Je comprends ces arguments. Je comprends aussi 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.

Modifier: cette partie a été ajoutée ...

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

Était-ce utile?

La solution

Vous pouvez y arriver 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 figurer dans votre page <head> et tous les gestionnaires d'événements jQuery ready devraient figurer dans <body> pour éviter les erreurs (bien que cela ne soit pas infaillible!).

Une autre raison de ne pas utiliser l'utilisation de jQuery hébergé par Google est que, dans certains pays, le nom de domaine de Google est interdit.

Autres conseils

Le moyen le plus simple et le plus propre de procéder 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>

Pour cela, il utilise l'objet google qui a appelé http://www.google.com/ jsapi est chargé sur 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 teste également la présence de window.google.load. Je pourrais également effectuer une typeof vérification pour vérifier que les objets sont des objets ou des fonctions appropriés. Mais je pense que cela fait le tour.

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

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 que je ne suis pas sûr que si cela concerne les visiteurs de votre site, vous devriez manipuler le API Google AJAX Libraries du tout.

Fait intéressant : Dans un premier temps, j'ai essayé d'utiliser un bloc try..catch dans différentes versions, mais je n'ai pas trouvé une combinaison aussi nette que celle-ci. 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 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();
    }
}]);

Ceci charge jQuery à partir de Google-cdn. Ensuite, il est vérifié si jQuery a été chargé avec succès. Sinon (& Quot; nope & Quot;), la version locale est chargée. Vos scripts personnels sont également chargés - les & "; Les 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 'MonApp.init'.

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

Il existe d'excellentes solutions ici, mais je voudrais aller 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.

Mes raisons sont 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'à modifier le numéro de version d'un fichier de configuration.

Voici la 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 la configuration de l'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 servira 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 ma configuration, 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 c’est peut-être une méthode élégante de maintenance de vos bibliothèques AJAX.

Gland

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 également utiliser ...

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

Vous pouvez utiliser votre fichier local en dernier recours.

Apparemment, 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.

Alors, voici la séquence: Google CDN = & Gt; Microsoft CDN = & Gt; 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 version la plus récente / ancienne de jQuery et du 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: Le chargement de jQuery a-t-il échoué? (cochez jQuery variable)

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?

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

Voici une excellente explication à ce sujet!

Implémente également les délais de chargement et les délais de chargement!

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 révélée fausse. Veuillez consulter les commentaires pour une explication réelle.

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 passer les deux copies?

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.

J'ai créé un Gist qui devrait charger dynamiquement jQuery s'il n'est pas déjà chargé et, si la 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();
}

JQuery hébergé sur Google

  • Si vous vous souciez des anciens navigateurs, principalement des versions d'IE antérieures à IE9, il s'agit de la version de jQuery la plus compatible.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  • Si vous & # 8217; ne vous souciez plus 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!

  • Quoi qu'il en soit, 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 susceptible), 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 cela devrait échapper au dernier < à \ x3C dans la chaîne. Lorsque le navigateur le voit, il considère qu'il s'agit de la fin du bloc de script (étant donné que 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>
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 les scripts avec 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 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 créer un assistant ( Vue d'ensemble de l'aide ):

@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 utilisez-le 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")

Bien que l'écriture document.write("<script></script>") semble plus facile pour le retour en arrière de jQuery, Chrome génère une erreur de validation dans ce cas. Je préfère donc rompre le & Quot; script & Quot; mot. Cela devient donc 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) En outre, il est préférable d’enregistrer 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 le code JavaScript de la vanille 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>

Il est difficile de charger la ressource à partir d'un magasin de données externe hors de votre contrôle. La recherche de fonctions manquantes est totalement fallacieuse pour éviter de perdre du temps, comme décrit dans ce document: http://www.tech-101.com/ support / topic / 4499-issues-using-a-cdn /

Encore une solution de rechange qui remplace ajax.googleapis.com par 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 captures HTML
  • Testé à l'état sauvage - fonctionne parfaitement pour les utilisateurs de Chine

Vous pouvez utiliser un code tel que:

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

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

Presque tous les CDN publics sont assez fiables. Toutefois, si vous craignez un domaine Google bloqué, vous pouvez simplement recourir à un autre CDN public tel que PageCDN , CDNJS ou jsDelivr :

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

Toutefois, dans ce cas, vous préférerez peut-être utiliser un autre CDN comme option de votre choix et opter pour le CDN Google afin d'éviter les demandes en attente et les délais 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>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top