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

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

Вопрос

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

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

Могу ли я настроить таймер и проверить наличие объекта jQuery?

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

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


Редактировать:Добавлена эта часть...

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

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


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

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

Это было полезно?

Решение

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

<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> чтобы избежать ошибок (хотя это и не защита от дураков!).

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

Другие советы

Самый простой и понятный способ сделать это на сегодняшний день:

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

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

<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 библиотек Google AJAX вообще.

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

Если у вас есть 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 успешно загружен.Если нет ("нет"), загружается локальная версия.Также загружаются ваши личные скрипты - "оба" указывает на то, что процесс загрузки запускается независимо от результата теста.

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

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

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

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

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

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

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

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

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

Желудь

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

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

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

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

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

Условно загрузите последнюю / устаревшую версию 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]-->
  • Шаг 1:Не удалось загрузить jQuery?(проверить jQuery переменная)

Как проверить не определенную переменную в JavaScript

  • Шаг 2:Динамический импорт (резервной копии) файла javascript

Как мне включить файл JavaScript в другой файл JavaScript?

Из-за проблемы с запретом Google я предпочитаю использовать cdn от Microsoft http://www.asp.net/ajaxlibrary/cdn.ashx

Вот отличное объяснение по этому поводу!

Также реализованы задержки загрузки и тайм-ауты!

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

Для тех, кто использует 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);

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


На большинство ваших вопросов были даны ответы, но что касается заключительной части:

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

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

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

Пожалуйста, обратите внимание, что я планирую постоянно обновлять суть, но не этот ответ, чего бы это ни стоило!

/* 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 Разместил jQuery

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

Я считаю, что должен избежать последнего < в \x3C в строке.Когда браузер видит, он считает, что это конец блока скрипта (поскольку анализатор 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>
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>

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

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

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

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

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

Еще один запасной вариант, который заменяет 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-фрагментами
  • Протестировано в дикой природе - идеально подходит для пользователей из Китая

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

<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
  • Требовать JS
  • епноуп

Примеры:

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

Требовать JS

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

Почти все общедоступные CDN работают довольно надежно.Однако, если вас беспокоит заблокированный домен Google, вы можете просто перейти на какой-нибудь другой общедоступный CDN, например PageCDN Страница, CDNJS или 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>

Однако в таком случае вы можете предпочесть использовать какой-либо другой 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>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top