问题描述

我正在尝试开发一个 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="' +
                    $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-family 属性。这是由 Font Awesome 设置的,所以如果不是 true,这意味着 CSS 没有加载。如果发生这种情况,代码使用 JavaScript 将本地 CSS 附加到头。

(要测试此代码,您可以通过 wp_enqueue_style 嵌入一个错误的 CDN URL,看看会发生什么)

因此,在极少数情况下,CDN 不可用,所有样式将按预期显示 (在几毫秒内,用户将看到’broken’ CSS 图标,因为 CSS 在页面加载后添加) 。

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

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。