Comment fournir un secours local pour Font Awesome si CDN échoue?


14

J'essaie de développer un thème Wordpress et de découvrir comment fournir un repli local pour Font Awesome si CDN échoue ou je développe mon thème sur un serveur local sans connexion Internet.

La solution que j'ai en tête est quelque chose comme ça (pseudo code):

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

Je vous remercie!


@Alexan Qu'en est-il is_readable($cdnPath)?
Mayeenul Islam

Merci @MayeenulIslam mais il semble renvoyer false même si le CDN est disponible.
Knott

2
Il y a - au moins - deux façons, mais la seule raison d'utiliser un CDN est la performance, mais je suis presque sûr que toute façon que vous trouverez améliorera les performances, donc imho n'a aucun sens. Si le thème est pour le partage / la vente, j'opterais pour une copie locale uniquement, en veillant à laisser aux utilisateurs un moyen facile de passer à la version CDN, s'ils le préfèrent. Si le thème est pour vous seul, choisissez-en un ou un autre. Considérez que la plupart des CDN célèbres ont un très faible% de temps d'arrêt (et bootstrapcdn est l'un des plus fiables, selon cdnperf.com ).
gmazzap

Avez-vous une idée générique sur la façon de gérer le repli pour les débutants? Je sais que les solutions de secours JS reposent sur la vérification des variables, je ne sais pas sur quoi s'appuyer pour vérifier la charge CSS.
Rarst

1
Bien sûr que vous le faites, je ne ferais jamais de demande supplémentaire de PHP pour cela. C'est le défi ici - pour commencer, je ne vois pas du tout de bonne façon de vérifier la charge CSS.
Rarst

Réponses:


15

Le problème est que je suis presque sûr qu'il est impossible de vérifier si CSS est effectivement ajouté à une page via PHP: CSS est analysé par le navigateur, donc côté client, et n'a aucun effet du côté serveur.

Bien sûr, en PHP, il est possible de vérifier si CDN est réactif ou non ...

Option 1

Envoyez une demande et si elle répond avec le statut HTTP 200, utilisez-la. Quelque chose comme:

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

cela se traduit par 2 requêtes HTTP, une pour la vérification, la seconde pour le CSS embarqué: vraiment mauvais .

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

C'est encore pire :

  • Cela ruine le wp_enqueue_styleflux de travail: si un plugin ajoute Font Awesome, il sera ajouté 2 fois.
  • Le nombre de requêtes HTTP est le même, cependant normalement les 2 requêtes s'exécutent en parallèle , donc de cette façon la génération PHP de la page ralentit car elle doit attendre la première réponse de la requête.
  • Cela empêche également le navigateur de mettre en cache le CSS, donc si vous utilisez le même style dans différentes pages, vous forcez la demande CDN sur chaque page visitée. Lorsque vous utilisez le workflow normal, les pages après le premier CSS sont extraites du cache.

Donc, vraiment, ne fais pas ça à la maison.

Ce qui compte vraiment, c'est qu'en utilisant PHP, vous pouvez vérifier la demande CDN, mais pas vérifier CSS, de sorte que tous vos efforts aboutissent à de moins bonnes performances plutôt qu'à de meilleures.

Sincèrement, si le vôtre est un thème public, je vous suggère d'utiliser uniquement la copie locale, offrant aux utilisateurs un moyen de choisir 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 );
    }
}

Les utilisateurs peuvent donc remplacer complètement la fonction à l'aide d'un thème enfant et peuvent également utiliser le 'font_awesome css_url'filtre pour modifier l'URL.

Considérez également que certains hébergeurs haut de gamme convertissent automatiquement les actifs locaux en CDN, et il existe des plugins qui permettent tout CDN; c'est la raison pour laquelle un thème public ne doit pas du tout utiliser CDN.

Si le thème est pour vous, faites un choix. Considérez que la plupart des CDN célèbres ont un très faible% de temps d'arrêt (et bootstrapcdn est l'un des plus fiables, selon cdnperf.com ). Je suis sûr que votre hébergement a un temps d'arrêt% supérieur à bootstrapcdn, donc les gens ont plus de chances de ne pas voir votre site du tout, plutôt que de le voir avec des icônes cassées.

La sale façon

Comme dit, PHP ne peut pas vérifier CSS, car le rendu CSS se produit côté client, mais vous pouvez utiliser la vérification côté client: JavaScript.

Intégrez d'abord CSS à l'aide de 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 );
} 

Après cela, ajoutez du JavaScript à votre pied de page:

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

Ce code s'exécute lorsque la page est chargée et vérifie si la plage invisible ajoutée au pied de page avec la classe «fa» a la propriété font-family définie sur «FontAwesome». Ceci est défini par Font Awesome, donc si ce n'est pas vrai, cela signifie que CSS n'est pas chargé. Si cela se produit, le code utilise JavaScript pour ajouter le CSS local à la tête.

(Pour tester ce code, vous pouvez l'intégrer via wp_enqueue_styleune mauvaise URL CDN et voir ce qui se passe)

Ainsi, dans les rares cas où un CDN n'est pas disponible, tous les styles seront affichés comme prévu (pendant quelques millisecondes, les utilisateurs verront des icônes CSS `` cassées '', car CSS est ajouté après le chargement de la page).

Maintenant, étant donné que les CDN sont très fiables, cela vaut-il la peine de faire ce piratage pour <1% des personnes qui verront des icônes cassées? La réponse à cette question vous appartient.


Cela fait longtemps que je n'ai pas vu une approche aussi complexe et profonde sur un sujet comme celui-ci. Cela m'a complètement effacé. Maintenant, je suppose que j'utiliserai CDN uniquement comme option de thème, laissant à l'utilisateur la liberté de choisir. Je vous remercie!
Knott le

Je cherche depuis longtemps une solution comme celle-ci, donc en ce qui concerne la dernière phrase qui demande "cela vaut-il la peine de faire ce hack pour <1% des personnes qui verront des icônes cassées?" Peut-être que l'ajout d'une roulette de chargement fonctionnerait?
Carl Alberto

2

Une vérification côté serveur n'est pas non plus à l'épreuve des balles. Si votre serveur est situé en Californie, votre chèque utilisera le centre de données du California CDN. Si votre utilisateur est situé en Chine, il utilise probablement un centre de données complètement différent. Du moins, c'est ainsi que je pense que cela fonctionne.

Quoi qu'il en soit, voici une solution jquery améliorée:

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>

génial, et une approche valable pour bien plus que des polices impressionnantes, merci pour le partage. Je devrais ajouter, également agnostique contrairement aux autres solutions ici et ailleurs dans SO par exemple.
oucil

1
Puisqu'il n'y a pas de délai, cela finira par charger Font Awesome deux fois si l'instance CDN termine le chargement après la vérification fontFamily.
Dan Dascalescu

1
@DanDascalescu Les fichiers CSS ne sont-ils pas chargés de manière synchrone (blocage) par défaut? Je crois que la page ne continuera pas tant que le CDN ne sera pas chargé ou échouera?
skibulk

1
CSS se charge de manière synchrone, mais la police elle-même ne se charge que lorsque le texte l'utilisant est rendu. Voici un JSbin qui le montre .
Dan Dascalescu
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.