Bagaimana cara menyediakan fallback lokal untuk Font Awesome jika CDN gagal?

13

Saya mencoba mengembangkan tema Wordpress dan mencari tahu cara menyediakan fallback lokal untuk Font Awesome jika CDN gagal atau saya mengembangkan tema saya di server lokal tanpa koneksi internet.

Solusi yang ada dalam pikiran saya adalah sesuatu seperti ini (kode semu):

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

Terima kasih!

Knott
sumber
1
Saya khawatir pertanyaannya tidak spesifik untuk WordPress. Mungkin pertanyaan ini cocok untuk Anda.
Mayeenul Islam
Mengapa kamu berpikir begitu? Saya sedang berbicara tentang pengembangan tema WordPress dan standar tertentu yang menyatakan bahwa jika versi CDN perpustakaan disertakan, salinan lokal harus disediakan sebagai cadangan. Bagaimanapun, terima kasih.
Knott
1
wp_enqueue_style()dan bagaimana bekerja dengannya adalah sesuai topik.
fuxia
2
Ada - setidaknya - beberapa cara, namun satu-satunya alasan untuk menggunakan CDN adalah kinerja, tetapi saya cukup yakin cara apa pun yang Anda temukan akan membuat kinerja lebih buruk, jadi imho tidak masuk akal. Jika tema adalah untuk dibagikan / dijual, saya akan menggunakan salinan lokal saja, pastikan untuk meninggalkan pengguna cara mudah untuk beralih ke versi CDN, jika mereka mau. Jika tema hanya untuk Anda sendiri, pilih satu atau yang lain. Pertimbangkan bahwa CDN paling terkenal memiliki% down time yang sangat rendah (dan bootstrapcdn adalah salah satu yang paling dapat diandalkan, menurut cdnperf.com ).
gmazzap
1
Ya tentu saja, saya tidak akan pernah membuat permintaan tambahan dari PHP untuk itu. Itulah tantangannya di sini - sebagai permulaan saya tidak bisa memikirkan cara yang baik untuk memeriksa beban CSS sama sekali.
Paling lambat

Jawaban:

14

Masalahnya adalah saya cukup yakin tidak mungkin untuk memeriksa apakah CSS secara efektif ditambahkan ke halaman melalui PHP: CSS diurai oleh browser, jadi sisi klien, dan sama sekali tidak berpengaruh di sisi server.

Tentu saja, dalam PHP dimungkinkan untuk memeriksa apakah CDN responsif atau tidak ...

Pilihan 1

Kirim permintaan dan jika ia merespons dengan status HTTP 200, gunakan itu. Sesuatu seperti:

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

yang menghasilkan 2 permintaan HTTP, satu untuk cek, yang kedua untuk embedded CSS: sangat buruk .

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

Ini bahkan lebih buruk :

  • Ini merusak wp_enqueue_stylealur kerja: jika sebuah plugin menambahkan Font Awesome, itu akan ditambahkan 2 kali.
  • Jumlah permintaan HTTP adalah sama, namun biasanya 2 permintaan berjalan secara paralel , jadi dengan cara ini generasi PHP halaman melambat karena perlu menunggu respons permintaan pertama.
  • Ini juga mencegah browser dari caching CSS, jadi jika Anda menggunakan gaya yang sama di halaman yang berbeda, Anda memaksa permintaan CDN pada setiap halaman yang dikunjungi. Saat menggunakan alur kerja normal, halaman setelah CSS pertama diambil dari cache.

Jadi, sungguh, jangan lakukan ini di rumah.

Yang benar-benar penting adalah bahwa menggunakan PHP Anda dapat memeriksa permintaan CDN, tetapi tidak memverifikasi CSS, jadi semua upaya Anda berakhir dengan kinerja yang lebih buruk, bukannya lebih baik.

Hormat kami, jika tema Anda adalah tema publik, saya sarankan Anda hanya menggunakan salinan lokal, memberikan pengguna cara untuk memilih 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 );
    }
}

Jadi pengguna dapat sepenuhnya menimpa fungsi menggunakan tema anak, dan juga dapat menggunakan 'font_awesome css_url'filter untuk mengubah URL.

Juga pertimbangkan bahwa beberapa penyedia hosting kelas atas secara otomatis mengkonversi aset lokal ke yang CDN, dan ada plugin yang memungkinkan CDN semua hal; inilah alasan mengapa tema publik tidak boleh menggunakan CDN sama sekali.

Jika tema itu untuk Anda sendiri, maka buatlah pilihan. Pertimbangkan bahwa CDN paling terkenal memiliki% down time yang sangat rendah (dan bootstrapcdn adalah salah satu yang paling dapat diandalkan, menurut cdnperf.com ). Saya cukup yakin hosting Anda memiliki waktu henti% lebih besar dari bootstrapcdn, sehingga orang-orang memiliki kemungkinan lebih besar untuk tidak melihat situs Anda sama sekali, daripada melihatnya dengan ikon yang rusak.

Cara yang kotor

Seperti yang dikatakan, PHP tidak dapat memeriksa CSS, karena rendering CSS terjadi pada sisi klien, tetapi Anda dapat menggunakan pemeriksaan sisi klien: JavaScript.

Sematkan dulu CSS menggunakan 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 );
} 

Setelah itu, tambahkan beberapa JavaScript ke catatan kaki Anda:

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

Kode ini berjalan ketika halaman dimuat dan memeriksa apakah rentang tak terlihat ditambahkan ke footer dengan kelas 'fa' memiliki properti font-family diatur ke 'FontAwesome'. Ini diatur oleh Font Awesome, jadi jika itu tidak benar, itu berarti bahwa CSS tidak dimuat. Jika itu terjadi, kode tersebut menggunakan JavaScript untuk menambahkan CSS lokal ke kepala.

(Untuk menguji kode ini, Anda dapat menyematkan melalui wp_enqueue_styleURL CDN yang salah, dan lihat apa yang terjadi)

Jadi, dalam kasus langka CDN tidak tersedia, semua gaya akan ditampilkan seperti yang diharapkan (untuk beberapa milidetik pengguna akan melihat ikon CSS 'rusak', karena CSS ditambahkan setelah halaman dimuat).

Sekarang, mengingat CDN sangat andal, apakah pantas melakukan peretasan ini untuk <1% orang yang akan melihat ikon rusak? Menjawab pertanyaan ini terserah Anda.

gmazzap
sumber
Sudah lama saya tidak melihat pendekatan yang kompleks dan mendalam pada topik seperti ini. Itu membuat saya benar-benar bersih. Sekarang saya kira saya akan menggunakan CDN hanya sebagai opsi tema, meninggalkan kebebasan pengguna untuk memilih. Terima kasih!
Knott
Saya telah lama mencari solusi seperti ini, jadi mengenai kalimat terakhir yang menanyakan "apakah pantas melakukan peretasan ini untuk <1% orang yang akan melihat ikon yang rusak?" Mungkin menambahkan pemintal pemuatan akan berhasil?
Carl Alberto
1

Pemeriksaan sisi server juga tidak tahan peluru. Jika server Anda berlokasi di California, cek Anda akan menggunakan Pusat Data CDN California. Jika pengguna Anda berada di China, mereka kemungkinan akan menggunakan Pusat Data yang sama sekali berbeda. Setidaknya, begitulah menurut saya cara kerjanya.

Bagaimanapun, inilah solusi jquery yang ditingkatkan:

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
sumber
brilian, dan pendekatan yang valid untuk lebih dari font-mengagumkan, terima kasih telah berbagi. Saya harus menambahkan, juga agnostik tidak seperti solusi lain di sini dan di tempat lain di SO misalnya.
oucil
1
Karena tidak ada batas waktu, ini akan berakhir memuat Font Awesome dua kali jika instance CDN selesai memuat setelah pemeriksaan fontFamily.
Dan Dascalescu
@DanDascalescu Bukankah file CSS dimuat secara sinkron (memblokir) secara default? Saya percaya halaman tidak akan berlanjut sampai CDN dimuat atau gagal?
skibulk
CSS memang memuat secara sinkron, tetapi font itu sendiri memuat hanya ketika teks yang menggunakannya diterjemahkan. Inilah JSbin yang menunjukkan hal itu .
Dan Dascalescu