Come fornire un fallback locale per Font Awesome se la CDN fallisce?


14

Sto cercando di sviluppare un tema Wordpress e capire come fornire un fallback locale per Font Awesome se la CDN fallisce o sviluppo il mio tema su un server locale senza connessione a Internet.

La soluzione che ho in mente è qualcosa del genere (pseudo codice):

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

Grazie!



Grazie @MayeenulIslam ma sembra restituire falso anche il CDN è disponibile.
Knott,

2
Ci sono - almeno - un paio di modi, tuttavia l'unica ragione per usare un CDN è la performance, ma sono abbastanza sicuro che qualsiasi modo troverai di peggiorare le prestazioni, quindi imho non ha senso. Se il tema è per la condivisione / vendita, sceglierei solo una copia locale, assicurandomi di lasciare agli utenti un modo semplice per passare alla versione CDN, se preferiscono. Se il tema è solo per te, scegli uno o l'altro. Considera che i CDN più famosi hanno un tempo di inattività molto basso (e bootstrapcdn è uno dei più affidabili, secondo cdnperf.com ).
gmazzap

Hai un'idea generica su come gestire il fallback per i principianti? So che i fallback JS si basano sul controllo delle variabili, non sono sicuro su cosa fare affidamento sul controllo del caricamento CSS.
Rarst

1
Beh, certo che lo fai, non farei mai richieste extra da parte di PHP. Questa è la sfida qui - per i principianti non riesco a pensare a un buon modo per controllare il caricamento CSS.
Rarst

Risposte:


15

Il problema è che sono abbastanza sicuro che sia impossibile verificare se il CSS viene effettivamente aggiunto a una pagina tramite PHP: il CSS viene analizzato dal browser, quindi dal lato client, e non ha alcun effetto sul lato server.

Naturalmente, in PHP è possibile verificare se la CDN è reattiva o meno ...

opzione 1

Invia una richiesta e se risponde con lo stato HTTP 200, utilizzala. Qualcosa di simile a:

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

che risulta in 2 richieste HTTP, una per il controllo, la seconda per CSS incorporato: davvero pessima .

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

Questo è ancora peggio :

  • Rovina il wp_enqueue_styleflusso di lavoro: se un plugin aggiunge Font Awesome, verrà aggiunto 2 volte.
  • Il numero di richieste HTTP è lo stesso, tuttavia normalmente le 2 richieste vengono eseguite in parallelo , quindi in questo modo la generazione di pagine PHP rallenta perché deve attendere la risposta della prima richiesta.
  • Ciò impedisce inoltre al browser di memorizzare nella cache il CSS, quindi se si utilizza lo stesso stile in pagine diverse, si forza la richiesta CDN su ogni pagina visitata. Quando si utilizza il normale flusso di lavoro, le pagine dopo il primo CSS vengono prese dalla cache.

Quindi, davvero, non farlo a casa.

Ciò che conta davvero è che usando PHP puoi controllare la richiesta CDN, ma non verificare i CSS, quindi tutti i tuoi sforzi finiscono per ottenere prestazioni peggiori, anziché migliori.

Cordiali saluti, se il tuo è un tema pubblico, ti suggerisco di utilizzare solo la copia locale, fornendo agli utenti un modo per scegliere un 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 );
    }
}

Pertanto, gli utenti possono sostituire completamente la funzione utilizzando un tema figlio e possono anche utilizzare il 'font_awesome css_url'filtro per modificare l'URL.

Considera anche che alcuni provider di hosting di fascia alta convertono automaticamente le risorse locali in CDN e ci sono plugin che consentono a CDN tutto; questa è la ragione per cui un tema pubblico non dovrebbe usare affatto la CDN.

Se il tema è per te, fai una scelta. Considera che i CDN più famosi hanno un tempo di inattività molto basso (e bootstrapcdn è uno dei più affidabili, secondo cdnperf.com ). Sono abbastanza sicuro che il tuo hosting abbia un tempo di inattività% maggiore di bootstrapcdn, quindi le persone hanno più probabilità di non vedere affatto il tuo sito, che vederlo con icone spezzate.

Il modo sporco

Come detto, PHP non può controllare i CSS, perché il rendering CSS avviene sul lato client, ma puoi usare il controllo lato client: JavaScript.

Per prima cosa incorpora CSS usando 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 );
} 

Successivamente, aggiungi un po 'di JavaScript al tuo piè di pagina:

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

Questo codice viene eseguito quando la pagina viene caricata e verifica se l'intervallo invisibile aggiunto al piè di pagina con la classe 'fa' ha la proprietà della famiglia di caratteri impostata su 'FontAwesome'. Questo è impostato da Font Awesome, quindi se non è vero, significa che CSS non è caricato. In tal caso, il codice utilizza JavaScript per aggiungere il CSS locale a head.

(Per testare questo codice puoi incorporarlo tramite wp_enqueue_styleun URL CDN errato e vedere cosa succede)

Quindi, nel raro caso in cui un CDN non sia disponibile, tutti gli stili verranno mostrati come previsto (per alcuni millisecondi gli utenti vedranno icone CSS "rotte", poiché il CSS viene aggiunto dopo il caricamento della pagina).

Ora, considerando che le CDN sono molto affidabili, vale la pena fare questo hack per l'1% delle persone che vedranno icone rotte? Rispondere a questa domanda è lasciato a te.


Da molto tempo non vedo un approccio così complesso e profondo su un argomento come questo. Questo mi ha completamente cancellato. Ora suppongo che userò CDN solo come opzione del tema, lasciando all'utente la libertà di scegliere. Grazie!
Knott,

Ho cercato a lungo una soluzione come questa, quindi per quanto riguarda l'ultima frase che chiede "vale la pena fare questo hack per l'1% delle persone che vedranno icone rotte?" Forse l'aggiunta di un filatore di caricamento avrebbe funzionato?
Carl Alberto,

2

Un controllo sul lato server non è neanche a prova di proiettile. Se il tuo server si trova in California, il tuo controllo utilizzerà il Data Center della California CDN. Se l'utente si trova in Cina, probabilmente utilizzerà un Data Center completamente diverso. Almeno, è così che penso che funzioni.

Comunque, ecco una soluzione jquery migliorata:

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>

geniale, e un approccio valido per molto più di un fantastico font, grazie per la condivisione. Dovrei aggiungere, anche agnostico a differenza delle altre soluzioni qui e altrove in SO, ad esempio.
oucil,

1
Dato che non c'è timeout, questo finirà per caricare Font Awesome due volte se l'istanza CDN termina il caricamento dopo il controllo per fontFamily.
Dan Dascalescu,

1
@DanDascalescu I file CSS non vengono caricati in modo sincrono (blocco) per impostazione predefinita? Credo che la pagina non continuerà fino a quando la CDN non viene caricata o non riesce?
skibulk,

1
Il CSS si carica in modo sincrono, ma il carattere stesso si carica solo quando viene visualizzato il testo che lo utilizza. Ecco un JSbin che lo dimostra .
Dan Dascalescu,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.