Найкращий спосіб використовувати jQuery з розміщенням Google, але не вдалося повернутися до моєї розміщеної бібліотеки в Google


1016

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

Я не кажу, що Google лускатий. Бувають випадки, коли копія Google заблокована (мабуть, наприклад, в Ірані).

Я б встановив таймер і перевірив на предмет jQuery?

Яка небезпека виникнення обох примірників?

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


Редагувати: Ця частина додана ...

Оскільки Google пропонує використовувати google.load для завантаження бібліотек ajax, і він виконує зворотний виклик після завершення, мені цікаво, чи це ключ до серіалізації цієї проблеми.

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


Оновлення: jQuery зараз розміщений на CDN Microsoft.

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


9
Звичайно, перша відповідь була "не використовувати версію, розміщену в Google". :-)
Носредна

7
Звичайно, це було тому, що якщо ви хочете розмістити серйозний веб-сайт, ви не покладаєтесь на когось іншого, що розміщує ваші файли.
Брайан Мігліорісі

6
@Bryan Migliorisi, я вважаю, Twitter ще не такий серйозний? Але я визнаю, у них були проблеми з Google, як місяць тому, коли Google знизився.
Ionuț G. Stan

18
Користь використання Google чи ні для хостингу JS lib є гідною, але це обговорювалося в кількох інших темах. Я шукав технічні відповіді щодо запасу JS щодо затримок завантаження.
Носредна

2
@Joe Chung: Ймовірно, це кешування в системі користувача, що прискорить завантаження сторінки. Економить пропускну здатність. Використовує CDN Google. І т. Д.
Nosredna

Відповіді:


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>уникнути помилок (хоча це не дурень!).

Ще однією причиною не використовувати jQuery з розміщенням Google є те, що в деяких країнах доменне ім’я Google заборонено.


35
Ви вже не блокуєте (синхронно) завантаження JavaScript? Мені здається, випуск подвійної копії не був би проблемою.
Метт Шерман

68
Завантаження Javascript вже має бути синхронним, як сказав Метт Шерман. В іншому випадку багато проблем виникнуть, якщо сторінка спробувала виконати вбудований скрипт, який спирався на завантажену лише наполовину бібліотеку, або розширення бібліотеки було виконано без завантаження та виконання бібліотеки. Це також одна з причин, чому Yahoo YSlow рекомендує розміщувати JavaScript в кінці сторінок; щоб не блокувати завантаження інших елементів сторінки (включаючи стилі та зображення). Як мінімум, браузеру доведеться затримати виконання, щоб відбуватися послідовно.
розрив

42
Невелике виправлення від фанатику валідатора: Рядок '</' не дозволений у JavaScript, тому що його можна неправильно інтерпретувати як кінець тегу сценарію (короткий тег SGML-позначення). Натомість зробіть '<' + '/ script>'. Ура,
Болдевін

8
Цей приклад не спрацює. 1) якщо бібліотека Google ajax недоступна, доведеться спочатку вичерпати час, перш ніж вийти з ладу. Це може зайняти деякий час. У моєму тесті на відключення мого комп'ютера від мережі він просто спробував і спробував, і спробував, і не закінчився. 2) якщо (! 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>

1
@jpp не для XHTML 1.0іHTML 4.01
BenjaminRH

5
Люди продовжують просити мене видалити type="text/javascript"деталі, тому людям, які пишуть html для старих браузерів, зверніть увагу, що тепер вам доведеться додати це.
BenjaminRH

6
@BenjaminRH: type="text/javascript"в старих браузерах теж було непотрібно, оскільки всі вони за замовчуванням ставили Javascript. Дійсно старші браузери дивилися на languageатрибут; але навіть тоді Javascript був типовим, якщо атрибут відсутній.
Martijn

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 AJAX Libraries Google .

Факт забави : Спочатку я намагався використовувати блок try.catch для цього в різних версіях, але не зміг знайти комбінацію, яка була б такою чистою, як ця. Мені було б цікаво бачити інші втілення цієї ідеї, як лише вправу.


1
Яка перевага використання google.load у цій ситуації, а не завантаження ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js безпосередньо, як запропонував Rony? Я думаю, що завантаження його також безпосередньо сприймає проблеми із видаленими бібліотеками (що робити, якщо Google перестає обслуговувати JQuery 1.3.2). Крім того, версія Роні помічає проблеми з мережею ПІСЛЯ www.google.com/jsapi отримано, особливо коли jsapi завантажений з кешу? Можливо, вам потрібно буде використовувати зворотний виклик google.load (або, можливо, є якесь повернене значення для включення google.load у if (..)).
Ар’ян

Якщо хтось тестує на наявність Google.com, можна здійснити мережевий дзвінок, або можна перевірити наявність об’єкта "воротар". Що я роблю, це перевірка на предмет google та його функцію "load". Якщо обоє цих помилок, немає Google, і мені потрібна локальна версія. Версія Роні насправді цілком ігнорує URL-адресу www.google.com/jsapi, тому я не знаю, чому ви вказуєте, що вона буде отримана.
artlung

Зрештою, все, що потрібно, це завантаження бібліотеки jquery. Будь-яка бібліотека Google не є вимогою. У відповіді Роні можна точно знати, чи вдалось завантаження з Google (або кеша). Але у вашому чеку на "якщо (window.google && window.google.load)" бібліотека jquery все ще не завантажується. Фактичне завантаження бібліотеки jquery не перевірено?
Ар'ян

ах, я бачу, як я викликав плутанину. "Версія Роні помічає мережеві проблеми ПІСЛЯ www.google.com/jsapi отримана", слід краще читати: "Ваша версія не помічає мережевих проблем ПІСЛЯ www.google.com/jsapi була отримана".
Ар'ян

2
Нещодавно ми перейшли на використання Google як нашого хоста jQuery; якщо ми отримаємо будь-які повідомлення про помилки від заблокованих користувачів, я буду використовувати варіант вашої відповіді на рефакторинг нашого клієнтського коду. Хороша відповідь!
Jarrod Dixon

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 успішно завантажений. Якщо ні ("nope"), завантажується локальна версія. Також завантажуються ваші особисті сценарії - "обидва" вказують, що процес завантаження ініціюється незалежно від результату тесту.

Коли всі процеси завантаження завершені, виконується функція у випадку "MyApp.init".

Я особисто віддаю перевагу такому способу завантаження асинхронного сценарію. І оскільки я покладаюся на тести функціональних можливостей, які надає модернізатор при створенні сайту, я все-таки вбудував його на сайт. Тож насправді немає накладних витрат.


2
Я думаю, що ви пропускаєте точку запитання - як би ви почали завантажувати сценарій moernizr з CDN?
Джордж Філіппакос

2
Не можу рекомендувати завантажувати Modernizr з CDN. Слід скоріше отримати найменший на замовлення збір від modernizr.com
Емануель Клюге

2
Таким чином, цей варіант отримує +16, порівняно з 500/200 + отримують інші варіанти. Але це звучить цілком непогано. Це просто не популярно через те, що покладатися на Modernizer? Я випадково використовую Modernizer на нашому сайті так чи інакше, тому якщо це краще, ніж інші відповіді, може хтось мені повідомити? Я зовсім новачок у JQuery, тому уточнення оцінено.
redfox05

2
На час відповіді це було дійсно хорошим варіантом, але станом на 2015 рік yepnope.jsзастаріле. см stackoverflow.com/questions/33986561 / ...
Obmerk Kronen

Модернізр був створений для вирішення проблем саме як це питання. +1
Карлос Кіджано

21

Тут є кілька чудових рішень, але я хотів би зробити це на крок далі стосовно локального файлу.

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

Мої причини цього полягають у тому, що я хочу мати певний розум, коли йдеться про те, щоб відслідковувати, що я завантажую з Google, а також те, що я маю на локальному сервері. Якщо я хочу змінити версії, я хочу, щоб моя локальна копія синхронізувалася з тим, що я намагаюся завантажити з Google. У середовищі, де є багато розробників, я думаю, що найкращим підходом було б автоматизувати цей процес, щоб все, що потрібно було зробити, - це змінити номер версії у файлі конфігурації.

Ось запропоноване нами рішення, яке має працювати теоретично:

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

Теоретично, якщо мій код написаний належним чином, все, що мені потрібно зробити, - це змінити номер версії в конфігурації мого додатка, а потім віола! У вас є автоматичне резервне рішення, і вам не потрібно підтримувати фізичні файли на своєму сервері.

Що всі думають? Можливо, це надмірно, але це може бути елегантним методом підтримки ваших бібліотек AJAX.

Жолудь


Якщо ви робите всю цю роботу тільки для jQuery, то я б сказав, що це надмірно. Однак якщо у вас вже є деякі з цих компонентів для інших фрагментів вашої програми (наприклад, якщо ви вже завантажуєте сценарії з БД), це виглядає досить приємно.
Майкл Харен

1
+1 за те, що він був ґрунтовним та новим, хоча я не впевнений, що користь виправдовує час і складність розробника.
Cory House

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 виглядає більш чисто. Зверху є другорядний друкарський помилок, який я не можу очистити, оскільки його ery другорядні дві дужки після "невизначеного"
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> 

Чи справді потрібно більше, ніж один запасний варіант? якщо обидва офлайн-користувачі будуть чекати більше хвилини, перш ніж побачити ваш сайт
Джордж Філіпакос,

1
Не завантажується сценарій не одну хвилину, але це не так.
Едвард Оламісан

@ geo1701 та Едварда, третій справді не потрібен. Навіть один запас ще не був доведений надійним. Якщо Google API не працює, я ще не бачив жодних гарантій того, що перша спроба взагалі не вдасться. У мене випав
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



4

Ось чудове пояснення з цього приводу!

Також реалізує затримки завантаження та тайм-аути!

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


Відповіді лише на посилання не корисні і вважаються низькою якістю. Подумайте скопіювати відповідні біти у свою відповідь, з віднесенням звичайно до джерела.
random_user_name

@cale_b Ви жартуєте? Цій відповіді більше 7 років, тому такий коментар є невиправданим.
Стюарт.Склінар

Так, це стара відповідь. Хоча їх пропозиція справедлива. Відповіді, які є лише посиланнями в іншому місці, є кандидатами на видалення. Подальший читач: meta.stackoverflow.com/q/8259
Роб

Я повністю згоден, я б поміркував із пропозиціями сам - але безглуздо це говорити через 7 років. Це слід було б модерувати так, як 7 років тому, а не через 7 років.
Стюарт.Склінар

1
@ Stuart.Sklinar - якби я це бачив 7 років тому, я б мав :) Я опинився тут, роблячи деякі дослідження, і бачив це вперше. Вибачте, що вас засмучує - я думаю, що наші завдання в ТА - це бути керівниками сайту, що іноді означає коментувати, редагувати або покращувати старі питання чи відповіді ...
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

ОНОВЛЕННЯ:
Ця відповідь виявилася помилковою. Будь ласка, дивіться коментарі для реального пояснення.


Більшість із вас відповіли, але щодо заключної частини:

Яка небезпека виникнення обох примірників?

Жоден насправді. Ви втратите пропускну здатність, можете додати кілька мілісекунд для завантаження другої непотрібної копії, але фактичної шкоди немає, якщо вони обидва проникнуть. Вам, звичайно, слід уникати цього, використовуючи згадані вище методи.


5
Власне, завантаження jQuery двічі може спричинити багато проблем, відповідно до цього питання .
ShadowCat7

чому б ви не випробували його самостійно та вручну завантажували бібліотеку jquery двічі. тоді відповідь буде розкрита.
luke_mclachlan

Чому саме це так неправильно? @ ShadowCat7 Ви можете бути більш конкретними щодо проблем, які він викликає? Єдина проблема, яку я чітко визначив у зв'язаному вами питанні, - це "очищення всіх раніше завантажених плагінів". Але це не стосується завантаження одного і того ж файлу jQuery двічі "назад-назад", правда? Я запитую, тому що інші рішення місцевого резервного резерву настільки суперечливі, а document.write в деяких місцях є злом .
Боб Штейн

2

Я створив 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();
}

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

Я вважаю, що слід уникати останнього <до \ 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>

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);
Mirek Komárek

Відповідь Алекса не спрацює, якщо версія cdn не завантажена, оскільки браузер буде виконувати цю умову, і під час неї все ще завантажується решта javascripts, яким потрібен jquery, і він повертає помилку -> файли JavaScript, що завантажуються, заблокують запуск наступного фрагмента коду тож це не проблема .
alex

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

@maaartinus: Оскільки завантаження кожного сценарію CDN може вийти з ладу незалежно, вам потрібно перевірити кожне завантаження окремо. Немає надійного методу однієї перевірки CDN з подальшим завантаженням усіх скриптів з CDN проти локально.
Едвард Брей

Мене хвилює випадок - це збій на сайті CDN, що призводить до очікування багатьох завантажень. Тож я хотів би мати щось подібне try { for (Script s : ...) cdnLoad(s); } catch (...) { for (Script s : ...) ownLoad(s); }. Перекласти це на купу ifs може бути кошмаром.
maaartinus

1

Хоча написання document.write("<script></script>")здається простішим для backoff 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>


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
  • Випробуваний у природі - ідеально підходить для користувачів з Китаю

Чи можете ви детальніше розглянути наступне твердження: "Вам не потрібно піклуватися про версію 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
  • ПотрібноJS
  • 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
    });

Потрібно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

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');
    }
  }
}]);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.