Jak przywrócić lokalny arkusz stylów (nie skrypt), jeśli CDN nie powiedzie się

Łączę się z arkuszem stylów jQuery Mobile na CDN i chciałbym wrócić do mojej lokalnej wersji arkusza stylów, jeśli CDN zawiedzie. Dla skryptów rozwiązanie jest dobrze znane:

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

Chciałbym zrobić coś podobnego dla arkusza stylów:

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

Nie jestem pewien, czy można osiągnąć podobne podejście, ponieważ nie jestem pewien, czy przeglądarka blokuje się w taki sam sposób podczas linkowania skryptu, jak podczas ładowania skryptu (może jest możliwe załadowanie arkusza stylów w znacznik skryptu, a następnie wstrzyknąć go do strony)?

Moje pytanie brzmi: jak upewnić się, że arkusz stylów jest ładowany lokalnie, jeśli CDN zawiedzie ?

Author: Salman A, 2011-09-12

11 answers

Nie testowane między przeglądarkami, ale myślę, że to zadziała. Będzie musiał być po załadowaniu jquery choć, lub będziesz musiał przepisać go w zwykły 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>
 58
Author: katy lavallee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-16 04:32:54

Zakładając, że używasz tego samego CDN dla css i jQuery, dlaczego nie zrobić jednego testu i złapać to wszystko??

<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>
 28
Author: Mike Wills,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-19 16:04:38

Myślę, że pytanie brzmi, czy arkusz stylów jest załadowany, czy nie. Możliwe podejście jest następujące:

1) Dodaj specjalną regułę na końcu pliku CSS, np.:

#foo { display: none !important; }

2) Dodaj odpowiedni div w HTML:

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

3) na gotowym dokumencie sprawdź, czy #foo jest widoczny czy nie. Jeśli arkusz stylów został załadowany, nie będzie widoczny.

Demo tutaj -- wczytuje motyw jQuery-UI smoothness; żadna reguła nie jest dodawana do arkusza stylów.

 27
Author: Salman A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-13 07:16:28

Ten artykuł sugeruje kilka rozwiązań dla Bootstrap css http://eddmann.com/posts/providing-local-js-and-css-resources-for-cdn-fallbacks/

Alternatywnie działa to dla 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>
 6
Author: dc2009,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-10 15:25:08

Możesz być w stanie przetestować istnienie arkusza stylów w 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

Przetestuj coś specyficznego dla używanego pliku CSS.

 3
Author: Stefan Kendall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-12 04:15:09

Oto rozszerzenie odpowiedzi katy lavallee. Wszystko zawijałem w samoczynnie wykonującą się składnię jQuery, aby zapobiec kolizjom zmiennych i uruchomić skrypt na dom ready. Zrobiłem też skrypt niespecyficzny dla pojedynczego linku. Oznacza to, że teraz każdy link do arkusza stylów z atrybutem url "data-fallback" będzie automatycznie przetwarzany. Nie musisz twardo kodować adresów URL do tego skryptu, jak wcześniej.

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
Author: skibulk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-15 12:33:01

Czy naprawdę chcesz przejść tę ścieżkę javascript, aby załadować CSS w przypadku awarii CDN?

Nie myślałem o wszystkich implikacjach wydajności, ale stracisz kontrolę nad tym, kiedy CSS jest ładowany i ogólnie dla wydajności ładowania strony, CSS jest pierwszą rzeczą, którą chcesz pobrać po HTML.

Dlaczego nie zająć się tym na poziomie infrastruktury - mapować własną nazwę domeny na CDN, nadać jej krótki TTL, monitorować pliki na CDN (np. za pomocą Watchmouse lub coś innego), jeśli CDN zawiedzie, Zmień DNS na stronę kopii zapasowej.

Inne opcje, które mogą pomóc to "cache forever" na statycznej zawartości, ale nie ma gwarancji, że przeglądarka będzie je przechowywać oczywiście lub za pomocą app-cache.

W rzeczywistości, jak ktoś powiedział na górze, jeśli twój CDN jest zawodny zdobądź Nowy

Andy

 2
Author: Andy Davies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-17 07:00:32

Spójrz na te funkcje:

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

A oto vanilla JavaScript version:

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

Teraz funkcja rzeczywista:

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

Upewnij się, że AddLocalCss jest wywoływany w głowie.

Możesz również rozważyć użycie jednego z następujących sposobów wyjaśnionych w tej odpowiedzi :

Załaduj za pomocą AJAX

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

Załaduj za pomocą dynamicznie tworzonego

$('<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");

Lub

$('<style type="text/css">@import url("' + myStylesLocation + '")</style>')
    .appendTo("head");
 1
Author: Community,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:06

Można by użyć onerror za to:

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

{[2] } ma na celu unikanie nieskończonych pętli w przypadku, gdy fallback it self nie jest dostępny. Ale może być również używany do wielu awaryjnych.

Jednak obecnie działa to tylko w Firefoksie i Chrome.

 0
Author: Jan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-07 13:33:37

Prawdopodobnie użyłbym czegoś takiego jak yepnope.js

yepnope([{
  load: 'http:/­/ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js',
  complete: function () {
    if (!window.jQuery) {
      yepnope('local/jquery.min.js');
    }
  }
}]);

Wzięte z readme.

 -1
Author: Ben Schwarz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-17 05:15:41
//(load your cdn lib here first)

<script>window.jQuery || document.write("<script src='//me.com/path/jquery-1.x.min.js'>\x3C/script>")</script>
 -7
Author: crazy4groovy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-29 10:31:39