問題描述
我正在嘗試開發一個 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 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。