วิธีการจัดเตรียมทางเลือกในท้องถิ่นสำหรับ Font Awesome หาก CDN ล้มเหลว


14

ฉันกำลังพยายามพัฒนาธีม Wordpress และหาวิธีให้ทางเลือกในท้องถิ่นสำหรับ Font Awesome หาก CDN ล้มเหลวหรือฉันพัฒนาธีมของฉันบนเซิร์ฟเวอร์ภายในโดยไม่ต้องเชื่อมต่ออินเทอร์เน็ต

วิธีแก้ปัญหาที่ฉันมีอยู่ในใจคืออะไรแบบนี้ (รหัสหลอก):

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

ขอบคุณ!


@Alexan แล้วis_readable($cdnPath)ไงล่ะ?
Mayeenul Islam

ขอบคุณ @MayeenulIslam แต่ดูเหมือนว่าจะส่งคืนค่าเท็จแม้ CDN จะพร้อมใช้งาน
Knott

2
มีอย่างน้อยสองวิธีอย่างไรก็ตามเหตุผลเดียวที่ใช้ CDN คือประสิทธิภาพ แต่ฉันค่อนข้างแน่ใจว่าวิธีที่คุณจะพบจะทำให้ประสิทธิภาพแย่ลงดังนั้น imho จึงไม่มีเหตุผล หากชุดรูปแบบสำหรับการแบ่งปัน / ขายฉันจะไปสำหรับการคัดลอกในท้องถิ่นให้แน่ใจว่าจะให้ผู้ใช้วิธีที่ง่ายในการเปลี่ยนเป็นเวอร์ชั่น CDN หากพวกเขาต้องการ หากชุดรูปแบบมีไว้สำหรับตัวคุณเองเท่านั้นให้เลือกอย่างใดอย่างหนึ่ง พิจารณาว่า CDN ที่มีชื่อเสียงส่วนใหญ่มีเวลาในการดาวน์ไทม์ที่ต่ำมาก (และ bootstrapcdn เป็นหนึ่งที่เชื่อถือได้มากที่สุดตามcdnperf.com )
gmazzap

คุณมีความคิดทั่วไปว่าจะจัดการทางเลือกสำหรับผู้เริ่มต้นได้อย่างไร? ฉันรู้ว่า JS fallbacks พึ่งพาการตรวจสอบตัวแปรฉันไม่แน่ใจว่าต้องพึ่งพาการตรวจสอบโหลด CSS หรือไม่
Rarst

1
แน่นอนคุณทำฉันจะไม่ขอเพิ่มจาก PHP สำหรับที่ นั่นคือความท้าทายที่นี่ - สำหรับผู้เริ่มฉันไม่สามารถคิดวิธีที่ดีในการตรวจสอบโหลด CSS ได้เลย
Rarst

คำตอบ:


15

ปัญหาคือฉันค่อนข้างแน่ใจว่าเป็นไปไม่ได้ที่จะตรวจสอบว่า CSS ถูกเพิ่มไปยังหน้าอย่างมีประสิทธิภาพผ่านทาง PHP: CSS ถูกวิเคราะห์โดยเบราว์เซอร์ดังนั้นฝั่งไคลเอ็นต์และไม่มีผลกระทบใด ๆ กับฝั่งเซิร์ฟเวอร์

แน่นอนใน PHP เป็นไปได้ที่จะตรวจสอบว่า CDN ตอบสนองหรือไม่ ...

ตัวเลือกที่ 1

ส่งคำขอและถ้ามันตอบสนองด้วยสถานะ HTTP 200 ใช้มัน สิ่งที่ต้องการ:

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

ที่ส่งผลให้มีการร้องขอ HTTP 2 ครั้งสำหรับการตรวจสอบครั้งที่สองสำหรับการฝัง CSS: แย่มาก

ตัวเลือก 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 );
    }
}

นี่ยิ่งแย่กว่านี้อีก :

  • มันทำลายwp_enqueue_styleเวิร์กโฟลว์: หากปลั๊กอินเพิ่ม Font Awesome มันจะถูกเพิ่ม 2 ครั้ง
  • จำนวนคำขอ HTTP เหมือนกันอย่างไรก็ตามโดยทั่วไปคำขอ 2 คำขอจะทำงานแบบขนานดังนั้นด้วยวิธีนี้การสร้างหน้า PHP จะช้าลงเนื่องจากต้องรอการตอบกลับคำขอแรก
  • สิ่งนี้ยังป้องกันไม่ให้เบราว์เซอร์แคช CSS ดังนั้นหากคุณใช้สไตล์เดียวกันในหน้าเว็บที่แตกต่างกันคุณจะต้องบังคับใช้คำขอ CDN ในทุก ๆ หน้าที่เข้าชม เมื่อใช้เวิร์กโฟลว์ปกติหน้าหลังจาก CSS แรกถูกนำมาจากแคช

ดังนั้นอย่าทำที่บ้าน

สิ่งสำคัญคือการใช้ PHP คุณสามารถตรวจสอบคำขอ CDN แต่ไม่ตรวจสอบ CSS ดังนั้นความพยายามทั้งหมดของคุณจะจบลงด้วยประสิทธิภาพที่แย่ลงแทนที่จะดีกว่า

ขอแสดงความนับถือหากคุณเป็นธีมสาธารณะฉันขอแนะนำให้คุณใช้เฉพาะสำเนาในเครื่องเพื่อให้ผู้ใช้มีวิธีเลือก 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 );
    }
}

ดังนั้นผู้ใช้สามารถแทนที่ฟังก์ชั่นการใช้ชุดรูปแบบลูกและยังสามารถใช้'font_awesome css_url'ตัวกรองเพื่อเปลี่ยน URL

นอกจากนี้ให้พิจารณาด้วยว่าผู้ให้บริการโฮสติ้งระดับสูงบางคนจะแปลงสินทรัพย์ในท้องถิ่นเป็น CDN โดยอัตโนมัติและมีปลั๊กอินที่อนุญาตให้ทุกสิ่ง CDN; นี่คือเหตุผลที่ธีมสาธารณะไม่ควรใช้ CDN เลย

หากชุดรูปแบบสำหรับตัวคุณเองให้เลือก พิจารณาว่า CDN ที่มีชื่อเสียงส่วนใหญ่มีเวลาในการดาวน์ไทม์ที่ต่ำมาก (และ bootstrapcdn เป็นหนึ่งที่เชื่อถือได้มากที่สุดตามcdnperf.com ) ฉันค่อนข้างแน่ใจว่าโฮสติ้งของคุณมีการหยุดทำงาน% มากกว่า bootstrapcdn ดังนั้นผู้คนมีโอกาสมากที่จะไม่เห็นเว็บไซต์ของคุณเลยกว่าที่จะเห็นด้วยไอคอนที่ใช้งานไม่ได้

ทางสกปรก

ดังที่ได้กล่าวไว้ PHP ไม่สามารถตรวจสอบ CSS ได้เนื่องจากการแสดงผล CSS เกิดขึ้นฝั่งไคลเอ็นต์ แต่คุณสามารถใช้การตรวจสอบฝั่งไคลเอ็นต์: JavaScript

ฝัง CSS ครั้งแรกโดยใช้ 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 );
} 

หลังจากนั้นเพิ่ม JavaScript บางส่วนลงในส่วนท้ายของคุณ:

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

รหัสนี้จะทำงานเมื่อมีการโหลดหน้าเว็บและตรวจสอบว่าช่วงการมองไม่เห็นที่เพิ่มในส่วนท้ายด้วยคลาส 'fa' มีการตั้งค่าคุณสมบัติแบบอักษรตระกูลเป็น 'FontAwesome' ตั้งค่าโดย Font Awesome ดังนั้นหากไม่เป็นจริงแสดงว่า CSS ไม่โหลด หากเกิดขึ้นรหัสจะใช้ JavaScript เพื่อผนวก CSS ท้องถิ่นเพื่อมุ่งหน้า

(ในการทดสอบรหัสนี้คุณสามารถฝังผ่านwp_enqueue_styleURL CDN ผิดและดูว่าเกิดอะไรขึ้น)

ดังนั้นในกรณีที่หายาก CDN ไม่พร้อมใช้งานสไตล์ทั้งหมดจะแสดงตามที่คาดไว้ (สำหรับผู้ใช้บางมิลลิวินาทีจะเห็นไอคอน CSS 'ที่เสีย' เนื่องจาก CSS ถูกเพิ่มหลังจากโหลดหน้าเว็บแล้ว)

ตอนนี้เมื่อพิจารณาว่า CDN มีความน่าเชื่อถือมากมันคุ้มค่าที่จะทำแฮ็คนี้สำหรับคน <1% ที่จะเห็นไอคอนแตกหรือไม่ การตอบคำถามนี้เหลือไว้สำหรับคุณ


นานมาแล้วที่ฉันไม่ได้เห็นแนวทางที่ซับซ้อนและลึกซึ้งเช่นนี้ในหัวข้อนี้ นั่นทำให้ฉันหมดจด ตอนนี้ฉันเดาว่าฉันจะใช้ CDN เป็นตัวเลือกชุดรูปแบบโดยปล่อยให้ผู้ใช้มีอิสระในการเลือก ขอบคุณ!
Knott

ฉันได้หาวิธีแก้ปัญหาเช่นนี้มานานแล้วดังนั้นเกี่ยวกับประโยคสุดท้ายที่ถามว่า "การแฮ็กนี้มีค่าสำหรับ <1% ของคนที่จะเห็นไอคอนแตกหรือไม่" อาจจะเพิ่มการโหลดปินเนอร์จะทำงานออกมา?
Carl Alberto

2

การตรวจสอบฝั่งเซิร์ฟเวอร์นั้นไม่ได้เป็นระบบป้องกันกระสุน หากเซิร์ฟเวอร์ของคุณอยู่ในแคลิฟอร์เนียเช็คของคุณจะใช้ศูนย์ข้อมูลของ California CDN หากผู้ใช้ของคุณอยู่ในประเทศจีนพวกเขาอาจจะใช้ศูนย์ข้อมูลที่แตกต่างอย่างสิ้นเชิง อย่างน้อยนั่นก็เป็นวิธีที่ฉันคิดว่าใช้ได้ผล

อย่างไรก็ตามต่อไปนี้เป็นโซลูชัน 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>

ยอดเยี่ยมและเป็นวิธีที่ถูกต้องมากกว่าแบบอักษรที่ยอดเยี่ยมขอบคุณสำหรับการแบ่งปัน ฉันควรจะเพิ่มผู้ไม่เชื่อเรื่องพระเจ้าซึ่งแตกต่างจากโซลูชันอื่น ๆ ที่นี่และที่อื่น ๆ ใน SO ดังนั้น
oucil

1
เนื่องจากไม่มีการหมดเวลานี้จะจบลงด้วยการโหลดแบบอักษรที่น่ากลัวสองครั้งถ้าเช่น CDN fontFamilyโหลดเสร็จหลังจากเช็คสำหรับ
Dan Dascalescu

1
@DanDascalescu ไฟล์ CSS ไม่โหลดพร้อมกัน (การบล็อก) โดยค่าเริ่มต้นหรือไม่ ฉันเชื่อว่าหน้าจะไม่ดำเนินการต่อจนกว่าจะโหลด CDN หรือล้มเหลว
skibulk

1
CSS ทำการโหลดแบบซิงโครนัส แต่ตัวอักษรจะโหลดเฉพาะเมื่อมีการแสดงข้อความที่ใช้ นี่คือการแสดงให้เห็นว่า JSbin
Dan Dascalescu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.