Wie kann ein lokaler Fallback für Font Awesome bereitgestellt werden, wenn CDN fehlschlägt?

13

Ich versuche, ein Wordpress-Theme zu entwickeln und herauszufinden, wie man einen lokalen Fallback für Font Awesome bereitstellt, wenn CDN fehlschlägt oder ich mein Theme auf einem lokalen Server ohne Internetverbindung entwickle.

Die Lösung, die ich vorhabe, ist ungefähr so ​​(Pseudocode):

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' );
    }

Vielen Dank!

Knott
quelle
1
Ich fürchte, die Frage ist nicht WordPress-spezifisch. Vielleicht passt diese Frage zu Ihnen.
Mayeenul Islam
Warum denkst du, dass? Ich spreche über die Entwicklung eines WordPress-Themas und bestimmter (tf) Standards, die besagen, dass eine lokale Kopie als Fallback bereitgestellt werden muss, wenn eine CDN-Version einer Bibliothek enthalten ist. Danke trotzdem.
Knott
1
wp_enqueue_style()und wie man damit arbeitet, ist themenbezogen.
Fuxia
2
Es gibt - zumindest - ein paar Möglichkeiten, aber der einzige Grund für die Verwendung eines CDN ist die Leistung, aber ich bin mir ziemlich sicher, dass jede Möglichkeit, die Sie finden, die Leistung verschlechtern wird, daher ergibt imho keinen Sinn. Wenn das Thema zum Teilen / Verkaufen bestimmt ist, würde ich nur lokale Kopien verwenden, um den Benutzern eine einfache Möglichkeit zu geben, auf die CDN-Version zu wechseln, wenn sie dies vorziehen. Wenn das Thema nur für Sie selbst bestimmt ist, wählen Sie das eine oder andere aus. Bedenken Sie, dass die meisten bekannten CDNs nur einen sehr geringen Prozentsatz an Ausfallzeiten haben (und Bootstrapcdn ist laut cdnperf.com eine der zuverlässigsten ).
gmazzap
1
Natürlich machst du das, ich würde nie extra PHP darum bitten. Das ist die Herausforderung hier - für den Anfang kann ich mir überhaupt keine gute Möglichkeit vorstellen, die CSS-Last zu überprüfen.
Rarst

Antworten:

14

Das Problem ist, dass ich mir ziemlich sicher bin, dass es unmöglich ist zu überprüfen, ob CSS einer Seite über PHP effektiv hinzugefügt wird: CSS wird vom Browser analysiert, also clientseitig, und hat keinerlei Auswirkungen auf die Serverseite.

Natürlich ist es in PHP möglich zu überprüfen, ob CDN reagiert oder nicht ...

Option 1

Senden Sie eine Anfrage und verwenden Sie diese, wenn diese mit dem HTTP-Status 200 antwortet. Etwas wie:

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 );
}

Das führt zu 2 HTTP-Anforderungen, eine für die Prüfung, die zweite für eingebettetes CSS: sehr schlecht .

Option 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 );
    }
}

Das ist noch schlimmer :

  • Es ruiniert den wp_enqueue_styleWorkflow: Wenn ein Plugin Font Awesome hinzufügt, wird es zweimal hinzugefügt.
  • Die Anzahl der HTTP-Anforderungen ist gleich, normalerweise werden jedoch zwei Anforderungen parallel ausgeführt . Auf diese Weise wird die PHP-Generierung der Seite verlangsamt, da auf die erste Antwort der Anforderung gewartet werden muss.
  • Dies verhindert auch, dass der Browser das CSS zwischenspeichert. Wenn Sie also denselben Stil auf verschiedenen Seiten verwenden, erzwingen Sie die CDN-Anforderung auf jeder besuchten Seite. Bei Verwendung des normalen Workflows werden die Seiten nach dem ersten CSS aus dem Cache entnommen.

Also wirklich nicht zu Hause.

Was wirklich wichtig ist, ist, dass Sie mit PHP die CDN-Anfrage überprüfen können, aber nicht CSS, sodass alle Ihre Bemühungen zu einer schlechteren Leistung führen, anstatt zu einer besseren.

Mit freundlichen Grüßen, wenn es sich bei Ihrem um ein öffentliches Thema handelt, empfehle ich, dass Sie nur die lokale Kopie verwenden, um Benutzern die Möglichkeit zu geben, eine CDN auszuwählen:

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 );
    }
}

So können Benutzer die Funktion mithilfe eines untergeordneten Themas vollständig überschreiben und mithilfe des 'font_awesome css_url'Filters die URL ändern.

Bedenken Sie auch, dass einige High-End-Hosting-Anbieter lokale Assets automatisch in CDN-Assets konvertieren, und dass es Plugins gibt , die CDN alle Dinge ermöglichen. Aus diesem Grund sollte ein öffentliches Thema CDN überhaupt nicht verwenden.

Wenn das Thema für Sie selbst bestimmt ist, treffen Sie eine Auswahl. Bedenken Sie, dass die meisten bekannten CDNs nur einen sehr geringen Prozentsatz an Ausfallzeiten haben (und Bootstrapcdn ist laut cdnperf.com eine der zuverlässigsten ). Ich bin mir ziemlich sicher, dass Ihr Hosting eine um% längere Ausfallzeit aufweist als bootstrapcdn, sodass die Wahrscheinlichkeit größer ist, dass Ihre Website überhaupt nicht angezeigt wird, als dass sie mit beschädigten Symbolen angezeigt wird.

Der schmutzige Weg

Wie gesagt, PHP kann CSS nicht überprüfen, da CSS clientseitig gerendert wird. Sie können jedoch die clientseitige Überprüfung verwenden: JavaScript.

Betten Sie zuerst CSS mit CDN ein:

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 );
} 

Fügen Sie anschließend etwas JavaScript in Ihre Fußzeile ein:

/*
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
});

Dieser Code wird ausgeführt, wenn die Seite geladen wird, und überprüft, ob für den unsichtbaren Bereich, der der Fußzeile mit der Klasse 'fa' hinzugefügt wurde, die Eigenschaft font-family auf 'FontAwesome' festgelegt ist. Dies wird von Font Awesome festgelegt. Wenn dies nicht der Fall ist, wird CSS nicht geladen. In diesem Fall hängt der Code mithilfe von JavaScript das lokale CSS an head an.

(Um diesen Code zu testen, können Sie ihn über wp_enqueue_styleeine falsche CDN-URL einbetten und sehen, was passiert.)

In dem seltenen Fall, dass eine CDN nicht verfügbar ist, werden alle Stile wie erwartet angezeigt (für einige Millisekunden sehen Benutzer "kaputte" CSS-Symbole, da CSS nach dem Laden der Seite hinzugefügt wird).

Wenn man bedenkt, dass CDNs sehr zuverlässig sind, lohnt es sich, diesen Hack für die <1% der Leute durchzuführen, die kaputte Symbole sehen werden? Die Beantwortung dieser Frage bleibt Ihnen überlassen.

gmazzap
quelle
Ich habe lange keine so komplexe und tiefgreifende Herangehensweise an ein solches Thema gesehen. Das hat mich komplett geklärt. Jetzt werde ich CDN vermutlich nur als Designoption verwenden, sodass der Benutzer die freie Wahl hat. Vielen Dank!
Knott
Ich habe lange nach einer solchen Lösung gesucht. Bezüglich des letzten Satzes, der fragt, ob es sich lohnt, diesen Hack für die <1% der Leute durchzuführen, die kaputte Symbole sehen werden. Vielleicht würde es klappen, einen Ladespinner hinzuzufügen?
Carl Alberto
1

Eine serverseitige Überprüfung ist ebenfalls nicht kugelsicher. Befindet sich Ihr Server in Kalifornien, verwendet Ihr Scheck das Rechenzentrum des kalifornischen CDN. Wenn sich Ihr Benutzer in China befindet, wird er wahrscheinlich ein völlig anderes Rechenzentrum verwenden. Zumindest denke ich, dass es so funktioniert.

Sowieso ist hier eine verbesserte jquery Lösung:

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
quelle
Genial, und ein gültiger Ansatz für viel mehr als nur Schriften - danke fürs Teilen. Ich sollte hinzufügen, auch agnostisch im Gegensatz zu den anderen Lösungen hier und anderswo in SO zum Beispiel.
oucil
1
Da keine Zeitüberschreitung auftritt, wird Font Awesome am Ende zweimal geladen, wenn die CDN-Instanz nach der Überprüfung auf den Inhalt fertig geladen ist fontFamily.
Dan Dascalescu
@DanDascalescu Werden CSS-Dateien nicht standardmäßig synchron geladen (blockiert)? Ich glaube, die Seite würde nicht fortgesetzt, bis der CDN geladen ist oder fehlschlägt?
Skibulk
CSS wird zwar synchron geladen, die Schriftart selbst wird jedoch nur geladen, wenn der Text, der sie verwendet, gerendert wird. Hier ist ein JSbin, der das zeigt .
Dan Dascalescu