問題描述

我正在嘗試開發一個 WordPress 主題,並找出如何提供一個本地的後備字型 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' );
    }

謝謝!

最佳解決方案

問題是,我很確定無法檢查 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 );
}

這導致 2 個 HTTP 請求,一個用於檢查,第二個用於嵌入式 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 請求的數量是相同的,但是通常兩個請求並行執行,因此,透過這種方式,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 。

還要考慮一些 high-end 託管服務提供商自動將本地資產轉換為 CDN,並且還有 plugins 允許 CDN 所有的東西; 這是公共主題不應該使用 CDN 的原因。

如果這個主題是為自己而設,那就做出選擇。考慮到大多數著名的 CDN 具有非常低的停機時間 (根據 cdnperf.com,bootstrapcdn 是最可靠的之一) 。我很確定你的主機的停機時間比 bootstrapcdn 大,所以人們有更多的可能性看不到你的網站,而不是看到它與破碎的圖示。

髒的方式

如上所述,PHP 無法檢查 CSS,因為 CSS 渲染髮生在客戶端,但您可以使用客戶端檢查:JavaScript 。

首先使用 CDN 嵌入 CSS:

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="http://'%20+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20$check.data('cssuri')%20+%20//%20This%20is%20the%20theme%20CSS%20folder%20URL%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'font-awesome/css/font-awesome.min.css" />';
                $('head').append( local );
            }
        });
    </script>
    <?php
});

此程式碼在頁面載入時執行,並檢查新增到具有類’fa’ 的頁尾的不可見範圍是否具有設定為’FontAwesome’ 的 font-family 屬性。這是由 Font Awesome 設定的,所以如果不是 true,這意味著 CSS 沒有載入。如果發生這種情況,程式碼使用 JavaScript 將本地 CSS 附加到頭。

(要測試此程式碼,您可以透過 wp_enqueue_style 嵌入一個錯誤的 CDN URL,看看會發生什麼)

因此,在極少數情況下,CDN 不可用,所有樣式將按預期顯示 (在幾毫秒內,使用者將看到’broken’ CSS 圖示,因為 CSS 在頁面載入後新增) 。

現在,考慮到 CDN 是非常可靠的,是否值得這樣做, 1%的人會看到破碎的圖示?回答這個問題給你。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。