Melhor maneira de usar jQuery hospedado do Google, mas cair de volta para a minha biblioteca hospedada no Google falhar

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

Pergunta

O que seria uma boa maneira de tentar carregar o jQuery hospedado no Google (ou outra Google hospedado libs), mas carregar minha cópia do jQuery se a tentativa do Google falhar?

Eu não estou dizendo Google é esquisito. Há casos em que a cópia do Google é bloqueado (aparentemente no Irã, por exemplo).

Será que eu configurar um temporizador e de verificação para o objeto jQuery?

Qual seria o perigo de ambas as cópias que vêm através?

Não é realmente à procura de respostas como "basta usar o Google" ou "apenas usar o seu próprio." Eu entendo estes argumentos. Eu também entendo que o usuário é provável que tenha a versão Google em cache. Estou pensando em fallbacks para a nuvem em geral.


Edit: Esta parte adicionado ...

Desde que o Google sugere o uso de google.load para carregar as bibliotecas ajax, e ele executa uma chamada de retorno quando terminar, eu estou querendo saber se isso é a chave para a serialização este problema.

Eu sei que soa um pouco louco. Eu só estou tentando descobrir se ele pode ser feito de uma maneira confiável ou não.


Update:. JQuery agora hospedado em CDN da Microsoft

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

Foi útil?

Solução

Você pode alcançá-lo assim:

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

Esta deve ser em <head> da sua página e todos os manipuladores de eventos prontos jQuery deve estar na <body> a erros a evitar (embora não seja à prova de idiota!).

Mais uma razão para jQuery não uso hospedada no Google é que, em alguns países, nome de domínio do Google é proibido.

Outras dicas

A maneira mais fácil e mais limpa para fazer isso de longe:

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

Isso parece funcionar para mim:

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

O modo como funciona é usar o objeto google que chamar http://www.google.com/jsapi cargas para o objeto window. Se esse objeto não está presente, estamos supondo que o acesso ao Google está falhando. Se for esse o caso, carregar uma cópia local usando document.write. (estou usando o meu próprio servidor, neste caso, utilize o seu próprio para testar isso).

Eu também teste para a presença de window.google.load - Eu também poderia fazer uma verificação typeof para ver que as coisas são objetos ou funções, conforme apropriado. Mas eu acho que isso faz o truque.

Aqui está apenas a lógica de carga, uma vez destaque de código parece falhar desde que eu postei a página HTML inteira eu estava testando:

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

Embora eu deva dizer, eu não tenho certeza de que, se esta é uma preocupação para os visitantes do site que você deve estar brincando com o Google AJAX Libraries API em tudo.

Curiosidade : Eu tentei inicialmente usar um bloco try..catch para isso em várias versões, mas não conseguiu encontrar uma combinação que foi limpo como este. Eu estaria interessado em ver outras implementações desta ideia, puramente como um exercício.

Se você tem Modernizr.js incorporados em seu site, você pode usar o built-in yepnope.js para carregar seus scripts de forma assíncrona -. Entre outros jQuery (com 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();
    }
}]);

Esta cargas jQuery do Google CDN. Posteriormente é verificada, se jQuery foi carregado com êxito. Se não ( "Não"), a versão local é carregado. Também seus scripts pessoais são carregados -. A "ambos" indica que o processo de carga é iniated independentemente do resultado do teste

Quando todos os carga-processos estão completos, a função é executada, no caso 'MyApp.init'.

Eu pessoalmente prefiro este modo de carregamento de script assíncrona. E como eu contar com o recurso de testes fornecidos pelo Modernizr ao construir um site, eu tê-lo embutido no site de qualquer maneira. Portanto, não há realmente nenhuma sobrecarga.

Há algumas grandes soluções aqui, mas eu vou gostaria de dar um passo adiante em relação ao arquivo local.

Em um cenário em que o Google não falhar, ele deve carregar uma fonte local, mas talvez um arquivo físico no servidor não é necessariamente a melhor opção. Eu trago este acima porque eu estou actualmente a implementar a mesma solução, só que eu quero cair de volta para um arquivo local que é gerada por uma fonte de dados.

As minhas razões para isso é que eu quero ter algum pedaço da mente quando se trata de manter o controle do que eu carregar a partir de Google vs. o que eu tenho no servidor local. Se eu quiser mudar versões, eu quero manter minha cópia local sincronizada com o que eu estou tentando carregar a partir do Google. Em um ambiente onde há muitos desenvolvedores, eu acho que a melhor abordagem seria automatizar esse processo para que todos um teria que fazer é mudar um número de versão em um arquivo de configuração.

Aqui está a minha solução proposta que deve funcionar na teoria:

  • Em um arquivo de configuração do aplicativo, vou armazenar 3 coisas: URL absoluta para a biblioteca, o URL para a API JavaScript, eo número da versão
  • Escreva uma classe que recebe o conteúdo do arquivo da própria biblioteca (recebe o URL de configuração app), armazena em minha fonte de dados com o nome e número de versão
  • Escrever um manipulador que puxa meu arquivo local fora do db e armazena em cache o arquivo até que o número de versão alterações.
  • Se isso acontecer a mudança (em meu aplicativo config), minha classe vai puxar o conteúdo do arquivo com base no número de versão, guardá-lo como um novo recorde na minha fonte de dados, em seguida, o manipulador vai chutar e servir-se da nova versão.

Em teoria, se meu código está escrito corretamente, tudo o que eu teria que fazer é mudar o número da versão em meu aplicativo de configuração, em seguida, viola! Você tem uma solução alternativa que é automatizado, e você não tem que manter os arquivos físicos no servidor.

O que todo mundo acha? Talvez este seja um exagero, mas poderia ser um método elegante de manter suas bibliotecas AJAX.

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

}

Depois de tentar incluir cópia do Google a partir do CDN.

Em HTML5, você não precisa definir o atributo type.

Você também pode usar ...

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

Você pode querer usar o seu arquivo local como um último recurso.

Parece a partir de agora não própria CDN do jQuery não suporta https. Se você, em seguida, pode querer carregar a partir de lá primeiro.

Então aqui está a sequência: Google CDN => Microsoft CDN => A sua cópia local.

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

condicionalmente carga latest / legado versão jQuery e fallback:

<!--[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]-->
  • Passo 1: Será que jQuery deixar de carga? (Cheque variável jQuery)

Como verificar uma variável não definida em JavaScript

  • Passo 2: dinamicamente importação (backup) de arquivos javascript

Como posso incluir um arquivo JavaScript em outro arquivo JavaScript?

Por causa do problema proibição do Google Eu prefiro usar CDN da Microsoft http://www.asp.net/ajaxlibrary/cdn.ashx

Aqui está uma grande explicação sobre isso!

Também atrasos implementos de carga e tempos de espera!

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

Para aquelas pessoas que usam ASP.NET MVC 5, adicione este código em seus BundleConfig.cs para permitir a CDN para 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);

UPDATE:
Essa resposta acabou por ser errado. Por favor, consulte os comentários para a explicação real.


A maioria de vocês pergunta foi respondida, mas como para a parte final:

Qual seria o perigo de ambas as cópias que vêm através?

Nenhum realmente. Você iria desperdiçar largura de banda, pode adicionar alguns milissegundos download de uma segunda cópia inútil, mas não há dano real se ambos passarem. Você deve, naturalmente, evitar isso usando as técnicas acima mencionadas.

Eu fiz uma Gist que deve carregar dinamicamente jQuery se ele já não está carregado, e se a fonte falhar, ele passa para fallbacks (costuradas junto de muitas respostas): https://gist.github.com/tigerhawkvok/9673154

Por favor, note que pretendo manter o Gist atualizado, mas não esta resposta, por que vale a pena!

/* 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();
}

Google Hospedado jQuery

  • Se você se preocupa com os navegadores mais antigos, principalmente as versões do IE antes IE9, esta é a versão jQuery mais amplamente compatível
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  • Se você não se preocupam com oldIE, este é menor e mais rápido:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

Backup / Plano Fallback!

  • De qualquer maneira, você deve usar um fallback para locais apenas no caso do Google CDN falhar (improvável) ou está bloqueado em um local que seus usuários acessar seu site a partir de (um pouco mais provável), como o Irã ou às vezes 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>

Referência: http://websitespeedoptimizations.com/ContentDeliveryNetworkPost.aspx

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

ou

if(!window.jQuery){

não funciona se a versão CDN não carregado, porque o navegador irá percorrer este estado e durante ainda baixando o resto de javascripts que precisa jQuery e ele retorna erro. Solução era scripts de carga através dessa condição.

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

Usando a sintaxe Navalha em ASP.NET, este código fornece suporte fallback e trabalha com uma raiz virtual:

@{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 fazer um ajudante ( helper visão geral ):

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

e usá-lo como este:

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

Apesar de escrever document.write("<script></script>") parece mais fácil para jQuery recuo, Chrome dá erro de validação sobre o caso. Então eu prefiro quebrar palavra "script". Assim torna-se mais seguro como acima.

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

Por questões de longo prazo, seria melhor para iniciar sessão fallbacks jQuery. No código acima, se a primeira CDN não é JQuery disponível é carregado a partir de outra CDN. Mas você poderia querer saber que errônea CDN e removê-lo permanentemente. (Neste caso, é caso muito excepcional) também é melhor para registrar problemas de fallback. Então você pode enviar casos errôneas com AJAX. Por causa de JQuery não está definido, você deve usar javascript baunilha para o pedido 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>

A incapacidade de carregar o recurso de uma loja de dados externos além de seu controle é difícil. Olhando para as funções em falta é totalmente enganosa como um meio para evitar que sofre um tempo de espera, tal como aqui descrito: http://www.tech-101.com/ suporte / tópico / 4499-questões-usando-a-CDN /

No entanto, outro fallback que substitui ajax.googleapis.com com 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);
  • Você pode ficar com uma versão jQuery, especificando-a na cadeia
  • Perfeito para Gestão de Ativos que não trabalho com HTML snips
  • Testado em estado selvagem - funciona perfeito para os usuários da China

Você pode usar o código como:

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

Mas também há bibliotecas que você pode usar para configurar vários possíveis fallbacks para seus scripts e otimizar o processo de carregamento:

  • basket.js
  • RequireJS
  • yepnope

Exemplos:

basket.js Acho que a melhor variante para agora. Vai cach seu script no localStorage, que irá acelerar próximos carregamentos. A chamada mais simples:

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

Isso irá retornar uma promessa e você pode fazê próxima chamada em caso de erro, ou dependências de carga em caso de sucesso:

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

Quase todos os CDNs públicas são bastante confiável. No entanto, se você está preocupado com domínio do Google bloqueado, então você pode simplesmente fallback para algum outro CDN Pública como 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>

No entanto, em tal caso, um, você pode preferir usar algum outro CDN como sua opção preferida e fallback para o Google CDN para evitar pedidos falhados e tempo de espera:

<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>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top