Jak zapewnić lokalną rezerwę dla Font Awesome, jeśli CDN zawiedzie?

14

Próbuję opracować motyw Wordpress i dowiedzieć się, jak zapewnić lokalną rezerwę dla Font Awesome, jeśli CDN zawiedzie lub opracuję swój motyw na lokalnym serwerze bez połączenia z Internetem.

Rozwiązanie, które mam na myśli, jest mniej więcej takie (pseudo kod):

if ( $CDN_IS_AVAILABLE ) { 
        wp_enqueue_style( 'font-awesome', '//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css', false );
    } else {
        wp_enqueue_style('font-awesome', get_template_directory_uri() . '/css/font-awesome/css/font-awesome.min.css', false, '4.0.3' );
    }

Dziękuję Ci!

Knott
źródło
@Alexan Co z tym is_readable($cdnPath)?
Mayeenul Islam
Dzięki @MayeenulIslam, ale wydaje się, że zwraca false, nawet CDN jest dostępny.
Knott
2
Jest - przynajmniej - kilka sposobów, jednak jedynym powodem do korzystania z CDN jest wydajność, ale jestem pewien, że jakikolwiek sposób, który znajdziesz, pogorszy wydajność, więc imho nie ma sensu. Jeśli tematem jest udostępnianie / sprzedaż, wybrałbym tylko kopię lokalną, pozostawiając użytkownikom łatwy sposób na przejście do wersji CDN, jeśli wolą. Jeśli motyw jest tylko dla ciebie, wybierz jedno lub drugie. Weź pod uwagę, że najbardziej znane sieci CDN mają bardzo niski procent przestojów (a bootstrapcdn jest jednym z najbardziej niezawodnych, według cdnperf.com ).
gmazzap
Czy masz ogólny pomysł, jak radzić sobie z awarią na początek? Wiem, że awarie JS polegają na sprawdzaniu zmiennych, nie jestem pewien, na czym polegać przy sprawdzaniu obciążenia CSS.
Rarst
1
Oczywiście, że tak, nigdy nie poprosiłbym o to dodatkowego PHP. To wyzwanie tutaj - na początek nie mogę w ogóle wymyślić dobrego sposobu na sprawdzenie obciążenia CSS.
Rarst

Odpowiedzi:

15

Problem polega na tym, że jestem prawie pewien, że nie można sprawdzić, czy CSS jest skutecznie dodawany do strony przez PHP: CSS jest analizowany przez przeglądarkę, więc po stronie klienta i nie ma żadnego wpływu na stronę serwera.

Oczywiście w PHP można sprawdzić, czy CDN reaguje, czy nie ...

opcja 1

Wyślij żądanie, a jeśli odpowie ono statusem HTTP 200, użyj go. Coś jak:

function font_awesome_css() {
    $url = 'http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css';
    $cdn = wp_remote_get( $url );
    if ( (int) wp_remote_retrieve_response_code( $cdn) !== 200 ) {
        $url = get_template_directory_uri() . '/css/font-awesome/css/font-awesome.min.css';
    }
    wp_enqueue_style( 'font-awesome', $url, false );
}

co powoduje 2 żądania HTTP, jedno do sprawdzenia, drugie do wbudowanego CSS: naprawdę źle .

Opcja 2

function font_awesome_css() {
    $url = 'http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css';
    $cdn = wp_remote_get( $url );
    if ( (int) wp_remote_retrieve_response_code( $cdn ) === 200 ) {
        $css = wp_remote_retrieve_body( $cdn );
        add_action( 'wp_head', function() use( $css ) {
            $absolute = "//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts/";
            $css = str_replace( "../fonts/", $absolute, $css );
            echo '<style type="text/css">' . $css . '</style>';
        } );
    } else {
        $url = get_template_directory_uri() . '/css/font-awesome/css/font-awesome.min.css';
        wp_enqueue_style( 'font-awesome', $url, false );
    }
}

Jest jeszcze gorzej :

  • Rujnuje wp_enqueue_styleprzepływ pracy: jeśli wtyczka doda czcionkę Awesome, zostanie dodana 2 razy.
  • Liczba żądań HTTP jest taka sama, jednak zwykle 2 żądania działają równolegle , więc w ten sposób generowanie strony PHP spowalnia, ponieważ musi czekać na odpowiedź na pierwsze żądanie.
  • Zapobiega to również buforowaniu CSS przez przeglądarkę, więc jeśli używasz tego samego stylu na różnych stronach, wymuszasz żądanie CDN na każdej odwiedzanej stronie. Podczas korzystania z normalnego przepływu pracy strony po pierwszym CSS są pobierane z pamięci podręcznej.

Tak naprawdę nie rób tego w domu.

Ważne jest to, że za pomocą PHP można sprawdzić żądanie CDN, ale nie weryfikować CSS, więc wszystkie twoje wysiłki kończą się gorszą wydajnością, a nie lepszą.

Z poważaniem, jeśli twój jest motywem publicznym, sugeruję, abyś używał tylko kopii lokalnej, umożliwiając użytkownikom wybór CDN:

if ( ! function_exists( 'font_awesome_css' ) ) {
    function font_awesome_css() {
        $_url = get_template_directory_uri() . '/css/font-awesome/css/font-awesome.min.css';
        $url = apply_filters( 'font_awesome_css_url', $_url );
        wp_enqueue_style( 'font-awesome', $url, false );
    }
}

Dzięki temu użytkownicy mogą całkowicie zastąpić tę funkcję za pomocą motywu podrzędnego, a także mogą użyć 'font_awesome css_url'filtra do zmiany adresu URL.

Weź również pod uwagę, że niektórzy wysokiej klasy dostawcy hostingu automatycznie przekształcają zasoby lokalne na CDN, a istnieją wtyczki, które pozwalają CDN na wszystkie te rzeczy; jest to powód, dla którego motyw publiczny nie powinien w ogóle używać CDN.

Jeśli motyw jest dla Ciebie, dokonaj wyboru. Weź pod uwagę, że najbardziej znane sieci CDN mają bardzo niski procent przestojów (a bootstrapcdn jest jednym z najbardziej niezawodnych, według cdnperf.com ). Jestem prawie pewien, że twój hosting ma% przestoju większy niż bootstrapcdn, więc ludzie mają większe prawdopodobieństwo, że w ogóle nie zobaczą twojej witryny, niż zepsutymi ikonami.

Brudna droga

Jak już powiedziano, PHP nie może sprawdzić CSS, ponieważ renderowanie CSS odbywa się po stronie klienta, ale można użyć sprawdzania po stronie klienta: JavaScript.

Najpierw umieść CSS za pomocą CDN:

function font_awesome_css() {
    $url =  '//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css';
    wp_enqueue_style( 'font-awesome', $url, false );
} 

Następnie dodaj stopkę JavaScript do stopki:

/*
Normally the JS should be properly enqueued and the URL
passed via wp_enqueue_script, but this is a proof of concept,
more than real code.
*/
add_action( 'wp_footer', function() {
    $cssurl = get_template_directory_uri() . '/css/';
    ?>
    <span id="facheck" data-cssuri="<?php echo $cssurl; ?>" class="fa" style="display:none">
    </span>
    <script>
        jQuery(document).ready(function($) {
            var $check = $('#facheck');
            if ( $check.css('fontFamily') !== 'FontAwesome' ) {
                // Font Awesome not loaded!
                // Remove current CSS link
                $('#font-awesome-css').remove;
                // Add the local version
                var local = '<link rel="stylesheet" type="text/css" href="' +
                    $check.data('cssuri') + // This is the theme CSS folder URL
                    'font-awesome/css/font-awesome.min.css" />';
                $('head').append( local );
            }
        });
    </script>
    <?php
});

Ten kod jest uruchamiany podczas ładowania strony i sprawdza, czy niewidoczny zakres dodany do stopki w klasie „fa” ma właściwość font-family ustawioną na „FontAwesome”. Jest to ustawiane przez Font Awesome, więc jeśli to nieprawda, oznacza to, że CSS nie jest ładowany. Jeśli tak się stanie, kod używa JavaScript, aby dołączyć lokalny CSS do nagłówka.

(Aby przetestować ten kod, możesz osadzić za wp_enqueue_stylepomocą niewłaściwego adresu URL CDN i zobaczyć, co się stanie)

Dlatego w rzadkim przypadku, gdy CDN nie jest dostępny, wszystkie style będą wyświetlane zgodnie z oczekiwaniami (przez kilka milisekund użytkownicy zobaczą „zepsute” ikony CSS, ponieważ CSS jest dodawany po załadowaniu strony).

Teraz, biorąc pod uwagę, że CDN są bardzo niezawodne, czy warto wykonać ten hack dla <1% osób, które zobaczą zepsute ikony? Odpowiedź na to pytanie należy do Ciebie.

gmazzap
źródło
Dawno nie widziałem tak złożonego i głębokiego podejścia do takiego tematu. To całkowicie mnie oczyściło. Teraz chyba użyję CDN jako opcji motywu, pozostawiając użytkownikowi swobodę wyboru. Dziękuję Ci!
Knott,
Długo szukałem takiego rozwiązania, więc w odniesieniu do ostatniego zdania, które pyta: „czy warto zrobić ten hack dla <1% osób, które zobaczą zepsute ikony?” Może zadziałałoby dodanie tarczy ładującej?
Carl Alberto,
2

Sprawdzanie po stronie serwera również nie jest kuloodporne. Jeśli Twój serwer znajduje się w Kalifornii, czek będzie korzystał z centrum danych California CDN. Jeśli użytkownik znajduje się w Chinach, prawdopodobnie używałby zupełnie innego centrum danych. Przynajmniej tak myślę, że to działa.

Tak czy inaczej, oto ulepszone rozwiązanie jquery:

http://jsfiddle.net/skibulk/fp1gqnyc/

<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="/wordpress//css/font-awesome.min.css" rel="stylesheet">');
        }
        $span.remove();
    })(jQuery);
</script>
skibulk
źródło
genialne i prawidłowe podejście do czegoś więcej niż niesamowite czcionki, dzięki za udostępnianie. Powinienem dodać, także agnostyczny w przeciwieństwie do innych rozwiązań tutaj i gdzie indziej w SO.
oucil
1
Ponieważ nie ma limitu czasu, załadowanie Font Awesome zakończy się dwukrotnie, jeśli instancja CDN zakończy ładowanie po sprawdzeniu fontFamily.
Dan Dascalescu,
1
@DanDascalescu Czy pliki CSS nie są domyślnie ładowane synchronicznie (blokują)? Uważam, że strona nie będzie kontynuowana, dopóki CDN nie zostanie załadowana lub ulegnie awarii?
skibulk
1
CSS ładuje się synchronicznie, ale sama czcionka ładuje się tylko wtedy, gdy renderowany jest tekst za jej pomocą. Oto JSbin, który to pokazuje .
Dan Dascalescu,