如果CDN失败,如何为Font Awesom提供本地后备?

时间:2014-04-24 作者:Knott

我正在尝试开发一个Wordpress主题,并找出如何在CDN失败或我在没有internet连接的本地服务器上开发主题时为Font Awesome提供本地回退。

我想到的解决方案是这样的(伪代码):

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\' );
    }
谢谢大家!

2 个回复
最合适的回答,由SO网友:gmazzap 整理而成

问题是我很确定impossible 检查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请求,一个用于检查,另一个用于嵌入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 );
    }
}
这是公平的worse:

它破坏了wp_enqueue_style 工作流:如果插件添加了字体真棒,它将被添加2次don\'t 在家里这样做。

真正重要的是,使用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资产plugins 让CDN拥有一切;这就是公共主题根本不应该使用CDN的原因。

如果主题是为你自己,那么就做出选择。考虑到大多数著名的CDN的宕机时间百分比非常低(根据cdnperf.com). 我很确定你的主机的宕机时间比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="\' +
                    $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_style 错误的CDN URL,看看会发生什么)

因此,在罕见的CDN不可用的情况下,所有样式都将按预期显示(在几毫秒内,用户将看到“断开的”CSS图标,因为CSS是在页面加载后添加的)。

现在,考虑到CDN非常可靠,是否值得为<;1%的人会看到破碎的图标?回答这个问题就交给你了。

SO网友:skibulk

服务器端检查也不是防弹的。如果您的服务器位于加利福尼亚州,您的支票将使用加利福尼亚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="/css/font-awesome.min.css" rel="stylesheet">\');
        }
        $span.remove();
    })(jQuery);
</script>

结束

相关推荐

如何设置所有内容的CDN?

我知道可以使用W3 Total Cache为缓存内容设置CDN。但是,我如何使用WordPress设置CDN,以便最初将所有媒体内容(图像、视频、文件等)直接上载到CDN,而不是我的web主机/本地安装。我想完全绕过上传内容到我的托管帐户,只需通过CDN托管即可。例如:如果我通过WordPress上传了一幅图像,我希望它自动发送到CDN。