Как вернуться к локальной таблице стилей (не скрипту), если CDN не работает - PullRequest
101 голосов
/ 12 сентября 2011

Я ссылаюсь на таблицу стилей jQuery Mobile на CDN и хотел бы вернуться к моей локальной версии таблицы стилей в случае сбоя CDN.Для сценариев решение хорошо известно:

<!-- Load jQuery and jQuery mobile with fall back to local server -->
<script src="http://code.jquery.com/jquery-1.6.3.min.js"></script>
<script type="text/javascript">
  if (typeof jQuery == 'undefined') {
    document.write(unescape("%3Cscript src='jquery-1.6.3.min.js'%3E"));
  }
</script>

Я хотел бы сделать нечто подобное для таблицы стилей:

<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.css" />

Я не уверен, что подобный подход может быть достигнут, потому чтоЯ не уверен, блокирует ли браузер таким же образом при связывании сценария, как при загрузке сценария (может быть, возможно загрузить таблицу стилей в тег сценария и затем вставить ее на страницу)?

Итак, мой вопрос: как мне убедиться, что таблица стилей загружается локально в случае сбоя CDN?

Ответы [ 11 ]

60 голосов
/ 17 сентября 2011

Не проверено на разных браузерах, но, думаю, это будет работать.Должно быть, после загрузки jquery, или вам придется переписать его в простом Javascript.

<script type="text/javascript">
$.each(document.styleSheets, function(i,sheet){
  if(sheet.href=='http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.css') {
    var rules = sheet.rules ? sheet.rules : sheet.cssRules;
    if (rules.length == 0) {
      $('<link rel="stylesheet" type="text/css" href="path/to/local/jquery.mobile-1.0b3.min.css" />').appendTo('head');
    }
 }
})
</script>
28 голосов
/ 19 сентября 2011

Если вы используете один и тот же CDN для css и jQuery, почему бы просто не сделать один тест и поймать все это ??

<link href="//ajax.googleapis.com/ajax/libs/jqueryui/1/themes/start/jquery-ui.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script type="text/javascript">
    if (typeof jQuery == 'undefined') {
        document.write(unescape('%3Clink rel="stylesheet" type="text/css" href="../../Content/jquery-ui-1.8.16.custom.css" /%3E'));
        document.write(unescape('%3Cscript type="text/javascript" src="/jQuery/jquery-1.6.4.min.js" %3E%3C/script%3E'));
        document.write(unescape('%3Cscript type="text/javascript" src="/jQuery/jquery-ui-1.8.16.custom.min.js" %3E%3C/script%3E'));
    }
</script>
27 голосов
/ 17 сентября 2011

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

1) Добавьте специальное правило в конец вашего файла CSS, например:

#foo { display: none !important; }

2) Добавьте соответствующий div в ваш HTML:

<div id="foo"></div>

3) Когда документ готов, проверьте, является ли #foo видимым или нет. Если таблица стилей была загружена, она не будет видна.

Демо здесь - загружает тему гладкости jquery-ui; правило не добавляется в таблицу стилей.

7 голосов
/ 10 декабря 2014

эта статья предлагает некоторые решения для начальной загрузки css http://eddmann.com/posts/providing-local-js-and-css-resources-for-cdn-fallbacks/

в качестве альтернативы это работает для fontawesome

<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<script>
    (function($){
        var $span = $('<span class="fa" style="display:none"></span>').appendTo('body');
        if ($span.css('fontFamily') !== 'FontAwesome' ) {
            // Fallback Link
            $('head').append('<link href="/css/font-awesome.min.css" rel="stylesheet">');
        }
        $span.remove();
    })(jQuery);
</script>
3 голосов
/ 15 октября 2014

Вот продолжение ответа Кэти Лавалли.Я обернул все в синтаксис самовыполняемой функции, чтобы предотвратить конфликты переменных.Я также сделал скрипт не специфичным для одной ссылки.То есть теперь любая ссылка на таблицу стилей с атрибутом url «data-fallback» будет автоматически проанализирована.Вам не нужно жестко кодировать URL-адреса в этот скрипт, как раньше.Обратите внимание, что это должно выполняться в конце элемента <head>, а не в конце элемента <body>, в противном случае это может вызвать FOUC .

http://jsfiddle.net/skibulk/jnfgyrLt/

<link rel="stylesheet" type="text/css" href="broken-link.css" data-fallback="broken-link2.css">

.

(function($){
    var links = {};

    $( "link[data-fallback]" ).each( function( index, link ) {
        links[link.href] = link;
    });

    $.each( document.styleSheets, function(index, sheet) {
        if(links[sheet.href]) {
            var rules = sheet.rules ? sheet.rules : sheet.cssRules;
            if (rules.length == 0) {
                link = $(links[sheet.href]);
                link.attr( 'href', link.attr("data-fallback") );
            }
        }
    });
})(jQuery);
3 голосов
/ 12 сентября 2011

Вы можете быть в состоянии проверить наличие таблицы стилей в document.styleSheets.

var rules = [];
if (document.styleSheets[1].cssRules)
    rules = document.styleSheets[i].cssRules
else if (document.styleSheets[i].rules)
    rule= document.styleSheets[i].rules

Проверить что-то определенное для используемого вами CSS-файла.

2 голосов
/ 07 сентября 2018

Для этого можно использовать onerror:

<link rel="stylesheet" href="cdn.css" onerror="this.onerror=null;this.href='local.css';" />

this.onerror=null; позволяет избежать бесконечных циклов в случае, если сам по себе запасной вариант недоступен.Но его также можно использовать для нескольких откатов.

Однако в настоящее время это работает только в Firefox и Chrome.

2 голосов
/ 17 сентября 2011

Вы действительно хотите пойти по этому пути JavaScript, чтобы загрузить CSS в случае сбоя CDN?

Я не продумал все последствия для производительности, но вы потеряете контроль над тем, когда CSSи в целом для производительности загрузки страницы, CSS - это первое, что вы хотите загрузить после HTML.

Почему бы не обработать это на уровне инфраструктуры - сопоставьте свое собственное доменное имя с CDN, дайте емукороткий TTL, отслеживать файлы на CDN (например, с помощью Watchmouse или чего-то еще), если CDN дает сбой, измените DNS на резервный сайт.

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

На самом деле, как сказал кто-то сверху, если ваш CDN ненадежен, получите новый

Andy

1 голос
/ 12 сентября 2011

Посмотрите на эти функции:

$.ajax({
    url:'CSS URL HERE',
    type:'HEAD',
    error: function()
    {
        AddLocalCss();
    },
    success: function()
    {
        //file exists
    }
});

А вот ванильная версия JavaScript:

function UrlExists(url)
{
    var http = new XMLHttpRequest();
    http.open('HEAD', url, false);
    http.send();
    return http.status!=404;
}
if (!UrlExists('CSS URL HERE') {
AddLocalCss();
}

Теперь актуальная функция:

function AddLocalCss(){
document.write('<link rel="stylesheet" type="text/css" href=" LOCAL CSS URL HERE">')
}

Просто убедитесь, чтоВ голове вызывается AddLocalCss.

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

Загрузка с использованием AJAX

$.get(myStylesLocation, function(css)
{
   $('<style type="text/css"></style>')
      .html(css)
      .appendTo("head");
});

Загрузка с использованием динамически создаваемых

$('<link rel="stylesheet" type="text/css" href="'+myStylesLocation+'" >')
   .appendTo("head");
Load using dynamically-created <style>

$('<style type="text/css"></style>')
    .html('@import url("' + myStylesLocation + '")')
    .appendTo("head");

или

$('<style type="text/css">@import url("' + myStylesLocation + '")</style>')
    .appendTo("head");
0 голосов
/ 05 октября 2011
//(load your cdn lib here first)

<script>window.jQuery || document.write("<script src='//me.com/path/jquery-1.x.min.js'>\x3C/script>")</script>
...