Лучший способ использовать Google размещенный jQuery, но вернуться к моей размещенной библиотеке при сбое Google

Что было бы хорошим способом загрузить размещенный jQuery в Google (или другие размещенные в Google файлы), но загрузите мою копию jQuery, если попытка Google не удалась?

Я не говорю, что Google взломан. Бывают случаи, когда копия Google блокируется (например, в Иране).

Я установил бы таймер и проверил бы объект jQuery?

Какова была бы опасность прохождения обеих копий?

Не ищут ответы, например "просто используйте Google" или "просто используйте свои собственные". Я понимаю эти аргументы. Я также понимаю, что у пользователя, скорее всего, будет кеш-версия Google. Я думаю о резервных копиях для облака в целом.


Изменить: эта часть добавлена ​​...

Так как Google предлагает использовать google.load для загрузки библиотек ajax и выполняет обратный вызов, когда это делается, мне интересно, является ли это ключом к сериализации этой проблемы.

Я знаю, это звучит немного сумасшедшим. Я просто пытаюсь выяснить, можно ли это сделать надежным способом или нет.


Обновление: jQuery теперь размещен на Microsoft CDN.

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

Ответ 1

Вы можете добиться этого следующим образом:

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

Это должно быть на вашей странице <head>, и любые обработчики событий jQuery должны находиться в <body>, чтобы избежать ошибок (хотя это не безупречно!).

Еще одна причина использования не использования jQuery, размещенного в Google, заключается в том, что в некоторых странах доменное имя Google запрещено.

Ответ 2

Самый простой и чистый способ сделать это:

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

Ответ 3

Кажется, это работает для меня:

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

То, как это работает, заключается в использовании объекта google, вызывающего http://www.google.com/jsapi загружается в объект window. Если этого объекта нет, мы предполагаем, что доступ к Google не удался. Если это так, мы загружаем локальную копию с помощью document.write. (В этом случае я использую свой собственный сервер, пожалуйста, используйте его для тестирования).

Я также проверяю наличие window.google.load - я мог бы также сделать проверку typeof, чтобы увидеть, что объекты - это объекты или функции. Но я думаю, что это делает трюк.

Здесь просто логика загрузки, поскольку подсветка кода кажется неудачной, так как я опубликовал всю HTML-страницу, которую я тестировал:

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

Хотя я должен сказать, что я не уверен, что если это беспокоит посетителей вашего сайта, вы должны играть с API API AJAX Google вообще.

Фантастический факт. Сначала я попытался использовать блок try..catch для этого в разных версиях, но не смог найти комбинацию, которая была такой же чистой, как эта. Мне было бы интересно увидеть другие реализации этой идеи, просто как упражнение.

Ответ 4

Если на вашем сайте есть внедренные на вашем сайте объекты modernizr.js, вы можете использовать встроенный yepnope.js для асинхронного загрузки ваших скриптов - среди других jQuery (с резервным).

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

Это загружает jQuery из Google-cdn. После этого он проверяется, если jQuery был успешно загружен. Если нет ("nope"), загружается локальная версия. Также загружаются ваши личные сценарии - "оба" указывают, что процесс загрузки инициализируется независимо от результата теста.

Когда все процессы загрузки завершены, функция выполняется в случае "MyApp.init".

Я лично предпочитаю этот способ загрузки асинхронного сценария. И поскольку я полагаюсь на функциональные тесты, предоставляемые modernizr при создании сайта, я все равно встраивал его на сайт. Так что на самом деле нет накладных расходов.

Ответ 5

Здесь есть несколько отличных решений, но я хотел бы сделать еще один шаг к локальному файлу.

В случае, когда Google не работает, он должен загружать локальный источник, но, возможно, физический файл на сервере не всегда является лучшим вариантом. Я использую это, потому что в настоящее время я реализую одно и то же решение, только хочу вернуться к локальному файлу, который генерируется источником данных.

Мои причины для этого - то, что я хочу иметь некоторое умение, когда дело доходит до отслеживания того, что я загружаю из Google, и того, что у меня есть на локальном сервере. Если я хочу изменить версии, я хочу, чтобы моя локальная копия синхронизировалась с тем, что я пытаюсь загрузить из Google. В среде, где есть много разработчиков, я думаю, что лучший подход - автоматизировать этот процесс, чтобы все, что нужно было сделать, это изменить номер версии в файле конфигурации.

Здесь мое предлагаемое решение, которое должно работать теоретически:

  • В файле конфигурации приложения я сохраню 3 вещи: абсолютный URL для библиотеки, URL-адрес JavaScript API и номер версии
  • Напишите класс, который получает содержимое файла самой библиотеки (получает URL из конфигурации приложения), сохраняет его в моем источнике данных с именем и номером версии
  • Напишите обработчик, который вытаскивает мой локальный файл из db и кэширует файл до тех пор, пока номер версии не изменится.
  • Если он изменится (в моей конфигурации приложения), мой класс вытащит содержимое файла на основе номера версии, сохранит его как новую запись в моем источнике данных, затем обработчик начнет загружать и обслуживать новую версию.

Теоретически, если мой код написан правильно, все, что мне нужно сделать, это изменить номер версии в моей конфигурации приложения, а не альт! У вас есть резервное решение, которое автоматизировано, и вам не нужно поддерживать физические файлы на вашем сервере.

Что думают все? Возможно, это слишком много, но это может быть элегантный способ поддержки ваших библиотек AJAX.

Желудь

Ответ 6

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

}

После того, как вы попытаетесь включить копию Google из CDN.

В HTML5 вам не нужно устанавливать атрибут type.

Вы также можете использовать...

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

Ответ 7

Возможно, вы захотите использовать локальный файл в качестве последнего средства.

Похоже, что теперь jQuery собственный CDN не поддерживает https. Если это так, вы можете сначала загрузить с него.

Итак, вот последовательность: Google CDN = > Microsoft CDN = > Ваша локальная копия.

<!-- load jQuery from Google CDN -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> 
<!-- fallback to Microsoft 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> 

Ответ 8

Условно загрузить последнюю версию/версию jQuery и резервное копирование:

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

Ответ 12

UPDATE:
Этот ответ оказался неправильным. Пожалуйста, ознакомьтесь с комментариями для настоящего объяснения.


Ответы на большинство из вас были отвечены, но что касается финальной части:

Какова была бы опасность прохождения обеих копий?

Нет. Вы теряете пропускную способность, можете добавить несколько миллисекунд, загружающих вторую бесполезную копию, но не наносит никакого вреда, если они оба пройдут. Вы должны, конечно, избегать этого, используя упомянутые выше техники.

Ответ 13

Для тех, кто использует ASP.NET MVC 5, добавьте этот код в свой BundleConfig.cs, чтобы включить CDN для 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);

Ответ 14

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

Или

if(!window.jQuery){

Не будет работать, если версия cdn не будет загружена, потому что браузер выполнит это условие и во время загрузки все остальные javascripts, которым нужен jQuery, и он возвращает ошибку. Решение заключалось в том, чтобы загрузить сценарии через это условие.

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

Ответ 15

Я считаю, что следует избегать последнего < на \x3C в строке. Когда браузер видит, он считает, что это конец блока script (поскольку парсер HTML не имеет понятия о JavaScript, он не может отличить что-то, что только что появляется в строке, и то, что на самом деле означает элемент script). Таким образом, буквально в JavaScript, что внутри HTML-страницы (в лучшем случае) вызывают ошибки, и (в худшем случае) - огромная дыра в безопасности.

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

Ответ 16

Я создал Gist, который должен динамически загружать jQuery, если он еще не загружен, и если источник не работает, он переходит на резервные копии (сшитые из многих ответов): https://gist.github.com/tigerhawkvok/9673154

Обратите внимание, что я планирую обновить Gist, но не этот ответ, за что он стоит!

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

Ответ 17

Google Hosted jQuery

  • Если вам нравятся более старые браузеры, в первую очередь версии IE до IE9, это наиболее распространенная версия jQuery
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  • Если вы не заботитесь о oldie, это меньше и быстрее:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

Резервный/резервный план!

  • В любом случае, вы должны использовать резервную копию для локального, если Google CDN завершится неудачно (маловероятно) или заблокирован в том месте, где ваши пользователи получают доступ к вашему сайту (несколько более вероятно), например, к Ирану или иногда к Китаю.
<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>

Ссылка: http://websitespeedoptimizations.com/ContentDeliveryNetworkPost.aspx

Ответ 18

Используя синтаксис Razor в ASP.NET, этот код обеспечивает резервную поддержку и работает с виртуальным корнем:

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

Или создайте помощника (вспомогательный обзор):

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

и используйте его следующим образом:

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

Ответ 19

Хотя запись document.write("<script></script>") кажется проще для jQuery backoff, Chrome дает ошибку проверки в этом случае. Поэтому я предпочитаю сломать слово "script". Таким образом, он становится более безопасным, как описано выше.

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

Для долгосрочных проблем лучше зарегистрировать резервные копии JQuery. В приведенном выше коде, если первый CDN недоступен, JQuery загружается из другого CDN. Но вы можете захотеть узнать этот ошибочный CDN и удалить его навсегда. (этот случай - очень исключительный случай). Также лучше записывать проблемы с резервным копированием. Таким образом, вы можете отправлять ошибочные случаи с помощью AJAX. Из-за JQuery не определено, вы должны использовать javascript для обработки запроса 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>

Ответ 20

Невозможно загрузить ресурс из внешнего хранилища данных, находящегося за пределами вашего контроля. Поиск недостающих функций является полностью ошибочным как средство избежать страдания тайм-аута, как описано здесь: http://www.tech-101.com/support/topic/4499-issues-using-a-cdn/

Ответ 21

Еще один запасной вариант, который заменяет ajax.googleapis.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);
  • Вы можете придерживаться версии jQuery, указав ее в строке
  • Идеально подходит для управления активами, который не работает с фрагментами HTML
  • Протестировано в дикой природе - отлично работает для пользователей из Китая

Ответ 22

Вы можете использовать код как:

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

Но также есть библиотеки, которые вы можете использовать для настройки нескольких возможных откатов для ваших скриптов и оптимизации процесса загрузки:

  • basket.js
  • RequireJS
  • yepnope

Примеры:

basket.js я думаю лучший вариант на данный момент. Кэширует ваш скрипт в localStorage, что ускорит следующие загрузки. Самый простой вызов:

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

Это вернет обещание, и вы можете сделать следующий вызов в случае ошибки или загрузить зависимости в случае успеха:

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

Ответ 23

Почти все публичные CDN довольно надежны. Однако, если вы беспокоитесь о заблокированном домене Google, вы можете просто воспользоваться альтернативным jQuery CDN. Однако в таком случае вы можете предпочесть сделать это противоположным способом и использовать какой-либо другой CDN в качестве предпочтительного варианта и использовать Google CDN в качестве альтернативы, чтобы избежать неудачных запросов и времени ожидания:

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