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

1016

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

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

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

Какова будет опасность того, что обе копии будут получены?

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


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

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

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


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

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

Nosredna
источник
9
Конечно, первым ответом было «не используйте размещенную в Google версию». :-)
Носредна
7
Конечно, это было потому, что если вы хотите разместить серьезный веб-сайт, вы не полагаетесь на то, что кто-то еще хранит ваши файлы.
Брайан Мильориси
6
@Bryan Migliorisi, я думаю, что Twitter не так уж и серьезен? Но я признаю, что у них были свои проблемы с Google, как месяц назад, когда Google вышел из строя.
Ionuț G. Stan
18
Преимущества использования Google или нет для JS lib хостинга достойны, но это обсуждалось в нескольких других темах. Я искал технические ответы относительно JS-отклика на задержки загрузки.
Носредна
2
@Joe Chung: это, вероятно, будет кэшироваться в системе пользователя, ускоряя загрузку страницы. Спасает меня пропускная способность. Использует CDN от Google. И т.д.
Носредна

Ответы:

810

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

<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 запрещено.

Рони
источник
35
Разве скачивание javascript уже не блокируется (синхронно)? Мне кажется, проблема с двойным копированием не была бы проблемой.
Мэтт Шерман
68
Как сказал Мэтт Шерман, загрузка Javascript должна быть уже синхронной. В противном случае возникнет много проблем, если страница попытается выполнить встроенный сценарий, основанный на библиотеке, которая была загружена только наполовину, или расширение библиотеки будет выполнено без полной загрузки и выполнения библиотеки. Это также одна из причин, по которой Yahoo YSlow рекомендует размещать JavaScript в конце страниц; чтобы не блокировать загрузку других элементов страницы (включая стили и изображения). По крайней мере, браузер должен будет отложить выполнение, чтобы происходить последовательно.
gapple
42
Небольшое исправление от фанатика валидатора: строка «</» не разрешена в JavaScript, потому что она может быть неверно истолкована как конец тега сценария (нотация короткого тега SGML). Вместо этого сделайте '<' + '/ script>'. Приветствия,
Болдевин
8
Этот пример не будет работать. 1) если библиотека ajax Google недоступна, сначала придется отключить время ожидания, прежде чем произойдет сбой. Это может занять некоторое время. В моем тесте на отключение моего компьютера от сети он просто попробовал и попробовал и попытался, и время ожидания не истекло. 2) if (! JQuery) выдаст ошибку, потому что jQuery не определен, поэтому Javascript не знает, что с ним делать.
RedWolves
32
Чтобы проверить, был ли загружен jQuery, (! Window.jQuery) работает нормально, а затем закорачивается проверка typeof.
Йорн Зафферер
335

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

<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>
BenjaminRH
источник
1
@jpp не для XHTML 1.0иHTML 4.01
BenjaminRH
5
Люди продолжают просить меня удалить type="text/javascript"части, поэтому, если вы пишете html для старых браузеров, обратите внимание, что теперь вам придется добавить это.
BenjaminRH
6
@BenjaminRH: type="text/javascript"было ненужным и в старых браузерах, так как все они по умолчанию были в Javascript. Действительно старые браузеры смотрели на languageатрибут; но даже тогда Javascript был по умолчанию, если атрибут отсутствовал.
Мартейн
1
@Martijn Но мне понравился блестящий значок подтверждения :)
BenjaminRH
3
@ Trojan Вполне возможно, просто сложите вызовы. Обратите внимание, что в этот момент вы открываете новые узлы соединений, поэтому конвейер HTTP будет, вероятно, быстрее. ... <script src="//cdn1.com/jquery.js"></script> <script>window.jQuery || document.write('<script src="//cdn2.com/jquery.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="local/jquery.js"><\/script>')</script>
Том МакКензи,
76

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

<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 в разных версиях, но не смог найти такую ​​же чистую комбинацию, как эта. Мне было бы интересно увидеть другие реализации этой идеи, просто в качестве упражнения.

artlung
источник
1
В чем преимущество использования google.load в этой ситуации вместо прямой загрузки ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js, как предположил Рони? Я полагаю, что его загрузка напрямую улавливает проблемы с удаленными библиотеками (что если Google перестанет обслуживать JQuery 1.3.2). Кроме того, версия Рони замечает проблемы с сетью ПОСЛЕ www.google.com/jsapi, особенно когда jsapi загружен из кэша? Может потребоваться обратный вызов google.load, чтобы быть уверенным (или, может быть, есть какое-то возвращаемое значение, чтобы включить google.load в if (..)).
Арджан
Если кто-то проверяет наличие Google.com, он может сделать сетевой вызов или проверить наличие объекта «привратник». То, что я делаю, проверяет объект Google и его функцию «загрузки». Если оба из них не удается, нет Google, и мне нужна локальная версия. Версия Рони фактически полностью игнорирует URL-адрес www.google.com/jsapi, поэтому я не уверен, почему вы указываете, что он будет получен.
artlung
В конце концов, все, что требуется, это загрузить библиотеку jquery. Любая библиотека Google не является обязательной. В ответе Рони точно известно, если загрузка из Google (или из кэша) прошла успешно. Но при проверке «if (window.google && window.google.load)» библиотека jquery все еще не загружена. Фактическая загрузка библиотеки jquery не проверена?
Арджан
ах, я вижу, как я вызвал замешательство. «Версия Rony замечает проблемы с сетью ПОСЛЕ www.google.com/jsapi» - лучше прочитать: «Ваша версия не замечает проблем с сетью ПОСЛЕ www.google.com/jsapi».
Арджан
2
Недавно мы перешли на использование Google в качестве хоста jQuery; если мы получим какие-либо сообщения об ошибках от заблокированных пользователей, я буду использовать вариант вашего ответа для рефакторинга нашего клиентского кода. Хороший ответ!
Джаррод Диксон
30

Если у вас есть встроенный 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 при создании сайта, я все равно встраиваю его в сайт. Так что на самом деле нет накладных расходов.

Эмануэль Клюге
источник
2
Я думаю, что вы упускаете суть вопроса - как бы вы пошли на загрузку сценария moernizr из CDN?
Джордж Филиппакос
2
Я не могу рекомендовать загрузку Modernizr из CDN. Лучше всего получить наименьшую пользовательскую сборку от modernizr.com.
Эмануэль Клюге
2
Таким образом, эта опция получает +16, по сравнению с 500/200 + другие опции получают. Но это звучит довольно хорошо. Это просто не популярно из-за использования Модернизатора? В любом случае, я использую Modernizer на нашем сайте, так что, если это лучше, чем другие ответы, кто-нибудь может дать мне знать? Я довольно новичок в JQuery, поэтому уточнение приветствуется.
redfox05
2
Это был действительно хороший вариант во время ответа, но по состоянию на 2015 год yepnope.jsустарел. см. stackoverflow.com/questions/33986561/…
Обмерк Кронен
Modernizr был создан для решения проблем, как этот вопрос. +1
Карлос Кихано
21

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

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

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

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

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

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

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

Желудь

Желудь
источник
Если вы делаете всю эту работу только для jQuery, то я бы сказал, что это излишне. Однако, если у вас уже есть некоторые из этих компонентов для других частей вашего приложения (например, если вы уже загружаете скрипты из БД), то это выглядит довольно хорошо.
Майкл Харен
1
+1 за тщательность и новизну, хотя я не уверен, что выгода оправдывает время и сложность разработки.
Кори Дом
20
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>');
Алекс
источник
2
+1 выглядит чище. наверху есть небольшая опечатка, которую я не могу очистить, так как ее второстепенные две заключительные скобки после 'undefined'
naveen
1
Первый вариант позволяет избежать предупреждения Chrome[Violation] Avoid using document.write().
Боб Стейн
Первый вариант, к сожалению, не загружается синхронно . Второй вариант делает .
Боб Стейн
10

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

Похоже, что в настоящее время собственный 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> 
Эдвард Оламисан
источник
Есть ли необходимость в более чем одном запасном варианте? если оба пользователя офлайн, пользователь будет ждать более минуты, прежде чем увидит ваш сайт
George Filippakos
1
Сценарий не загружается за 1 минуту, делает это.
Эдвард Оламисан
@ geo1701 и Эдвард, Третий действительно не нужен. Даже один запасной вариант еще не доказал свою надежность. Если Google API не работает, я еще не видел никаких гарантий, что первая попытка потерпит неудачу вообще. Я столкнулся со сценарием, в котором CDN никогда не удавалось загрузить, удерживая страницу от любого
hexalys
6

Условно загрузите последнюю / устаревшую версию 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]-->
neiker
источник
Это не совместимо с разными браузерами.
Джош Хабдас
Джош, да, это так.
neiker
4

Вот отличное объяснение этого!

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

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

Stuart.Sklinar
источник
Ответы только на ссылки бесполезны и считаются некачественными. Попробуйте скопировать соответствующие биты в свой ответ, указав, конечно, источник.
random_user_name
@cale_b Ты что, шутишь? Этому ответу более 7 лет, поэтому такой комментарий неоправдан.
Stuart.Sklinar
Да, это старый ответ. Хотя их предложение действительно. Ответы, которые являются просто ссылками в другом месте, являются кандидатами на удаление. Дополнительный читатель: meta.stackoverflow.com/q/8259
Роб
Я полностью согласен, я бы сам модерировал предложения - но бессмысленно говорить об этом 7 лет спустя. Его следовало модерировать 7 лет назад, а не 7 лет спустя.
Stuart.Sklinar
1
@ Stuart.Sklinar - если бы я видел это 7 лет назад, я бы сделал это :) Я обнаружил, что здесь провожу некоторые исследования и вижу это впервые. Извините, что расстраиваю вас - я думаю, что наша работа на SO должна быть помощниками сайта, что иногда означает комментирование, редактирование или улучшение старых вопросов или ответов ...
random_user_name
4

Для тех, кто использует 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);
Мухаммед Рехан Саид
источник
4

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


Большинство из вас ответили на вопрос, но что касается заключительной части:

Какова будет опасность того, что обе копии будут получены?

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

WhyNotHugo
источник
5
На самом деле, загрузка jQuery дважды может вызвать много проблем, в соответствии с этим вопросом .
ShadowCat7
почему бы вам не проверить это самостоятельно и вручную загрузить библиотеку jquery дважды. тогда ответ будет раскрыт.
luke_mclachlan
Почему именно это так неправильно? @ ShadowCat7 Вы можете более конкретно рассказать о проблемах, которые это вызывает? Единственная проблема, которую я вижу в указанном вами вопросе, это «очистка всех ранее загруженных плагинов». Но это не должно относиться к загрузке одного и того же файла jQuery дважды подряд, верно? Я спрашиваю, потому что другие решения здесь для локального отступления настолько запутанны, а document.write в некоторых местах клеветает на зло .
Боб Стейн
2

Я сделал 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();
}
Филип Кан
источник
2

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

Райан
источник
Обратите внимание, что загрузка сценариев по незащищенным протоколам открывает вектор атаки XSS.
Джош Хабдас
2

Я считаю, что должен экранировать последний <to \ x3C в строке. Когда браузер видит, он считает, что это конец блока скрипта (поскольку анализатор HTML не имеет представления о JavaScript, он не может различить то, что просто появляется в строке, и то, что фактически предназначено для завершения скрипта. элемент). Поэтому появление буквально в 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>
JKhuang
источник
2
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>
Мирек Комарек
источник
Я обнаружил одну проблему при тестировании скриптов в Google Chrome - кеширование. Поэтому для локального тестирования просто замените src в секции else на что-то вроде s.src = 'my_javascripts.js' + '?' + Math.floor (Math.random () * 10001);
Мирек Комарек
Ответ Алекса не будет работать, если версия cdn не загружена, потому что браузер выполнит это условие и во время загрузки все еще загружает остальные javascripts, которым требуется jquery, и возвращает ошибку -> Загружаемые файлы JavaScript будут блокировать запуск следующего фрагмента кода так что это не проблема .
Алекс
2

Почти все публичные 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>
Хамид Сарфраз
источник
1

Используя синтаксис 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")
Эдвард Брей
источник
Я никогда не зацикливался на Razor, но он выглядит как обфускатор, за исключением того, что он делает код длиннее, а не короче (он вдвое длиннее этого .
maaartinus
@maaartinus: Это не сравнение яблок с яблоками. Ответ BenjaminRH, на который вы ссылаетесь, для одного сценария, размещенного на CDN. С CdnScriptпомощником вам потребуется только одна строка кода на скрипт . Чем больше у вас сценариев, тем больше отдача.
Эдвард Брей
Конечно ... это была просто напыщенная речь. Тем не менее, я думаю, что это не оптимальный путь. Если что-то не получится, я полностью проигнорирую CDN и переключусь на запасной вариант для всех сценариев. Я не уверен, выполнимо ли это, поскольку я не знаю, как именно работает загрузка.
Маартин
@maaartinus: Поскольку каждая загрузка сценария CDN может завершиться неудачей независимо, вы должны проверять каждую загрузку отдельно. Не существует надежного метода одиночной проверки CDN с последующей загрузкой всех сценариев из CDN по сравнению с локальными.
Эдвард Брей
Случай, который меня беспокоит, - это сбой сайта CDN, из-за которого приходится ожидать много загрузок. Так что я бы хотел что-то подобное try { for (Script s : ...) cdnLoad(s); } catch (...) { for (Script s : ...) ownLoad(s); }. Переводить это в кучу ifс может быть кошмаром.
Maaartinus
1

Несмотря на то, что запись 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 не определен, вы должны использовать vanilla 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>
trante
источник
1

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

jobeard
источник
0

Еще один запасной вариант, который заменяет 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
  • Протестировано в дикой природе - отлично работает для пользователей из Китая
redaxmedia
источник
Не могли бы вы уточнить следующее утверждение: «Вам не нужно заботиться о версии jQuery»?
Джош Хабдас
Версия является частью URL, который не будет затронут этим подходом ... jquery / 3.xx / jquery.min.js
redaxmedia
1
Может ли это привести к поломке, когда jQuery переходит на версию 4 и вносит обратно несовместимые изменения?
Джош Хабдас
-1, потому что это приведет к поломке, если jQuery внесет критические изменения, которые ваши скрипты не будут поддерживать, пока не указана версия.
Lookaji
@lookaji Я думаю, ты не понимаешь запасной вариант. Он заменяет домен, в котором он находится, и НЕ затрагивает имя файла / версию.
Redaxmedia
0

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

<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');
    }
  }
}]);
Роман Коптев
источник