Как обеспечить локальный запасной вариант для 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' );
    }

Спасибо!

Нотт
источник
@ Алексан Как насчет is_readable($cdnPath)?
Mayeenul Islam
Спасибо @MayeenulIslam, но, похоже, возвращает false, даже если CDN доступен.
Knott
2
Есть, по крайней мере, несколько способов, однако единственной причиной использования CDN является производительность, но я уверен, что любой найденный способ ухудшит производительность, поэтому imho не имеет смысла. Если тема предназначена для обмена / продажи, я бы пошел только на локальное копирование, оставляя пользователям простой способ перейти на CDN-версию, если они того пожелают. Если тема только для себя, выберите ту или иную. Учтите, что большинство известных CDN имеют очень низкий процент простоя (и bootstrapcdn является одним из самых надежных, согласно cdnperf.com ).
gmazzap
У вас есть общее представление о том, как справиться с резервированием для начинающих? Я знаю, что запасные варианты JS основаны на проверке переменных, я не уверен, на что можно полагаться при проверке загрузки CSS.
Первое
1
Ну, конечно, вы делаете, я бы никогда не сделал дополнительный запрос от PHP для этого. Вот в чем проблема - для начала я не могу придумать хороший способ проверить загрузку CSS вообще.
Первое

Ответы:

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

это приводит к 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-запросов одинаково, однако обычно 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», свойство font-family, установленное в «FontAwesome». Это устанавливается Font Awesome, поэтому, если это не так, это означает, что CSS не загружен. Если это происходит, код использует JavaScript для добавления локального CSS к заголовку.

(Чтобы проверить этот код, вы можете вставить его через wp_enqueue_styleнеправильный URL CDN и посмотреть, что получится)

Таким образом, в редких случаях CDN недоступен, все стили будут отображаться так, как ожидается (в течение нескольких миллисекунд пользователи будут видеть «сломанные» иконки CSS, потому что CSS добавляется после загрузки страницы).

Теперь, учитывая, что CDN очень надежны, стоит ли делать этот хак для <1% людей, которые увидят сломанные значки? Ответ на этот вопрос остается за вами.

Gmazzap
источник
Давно я не видел такого сложного и глубокого подхода к такой теме. Это полностью очистило меня. Теперь я предполагаю, что я буду использовать CDN просто как вариант темы, оставляя пользователю свободу выбора. Спасибо!
Нотт
Я долго искал решение, подобное этому, поэтому относительно последнего предложения, которое спрашивает: «Стоит ли делать этот хак для <1% людей, которые увидят сломанные значки?» Может быть, добавление загрузочного счетчика сработает?
Карл Альберто
2

Проверка на стороне сервера также не пуленепробиваема. Если ваш сервер находится в Калифорнии, ваш чек будет использовать центр обработки данных 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>
skibulk
источник
блестящий, и правильный подход для гораздо большего, чем просто потрясающий, спасибо за обмен. Я должен добавить, также агностик в отличие от других решений здесь и в других местах, например, в SO.
oucil
1
Поскольку время ожидания отсутствует, это приведет к двойной загрузке Font Awesome, если экземпляр CDN завершит загрузку после проверки fontFamily.
Дан Даскалеску
1
@DanDascalescu Разве CSS-файлы не загружаются синхронно (блокируются) по умолчанию? Я считаю, что страница не будет продолжаться до тех пор, пока CDN не загрузится или не выйдет из строя?
скибулк
1
CSS загружается синхронно, но сам шрифт загружается только при визуализации текста, использующего его. Вот JSbin, показывающий это .
Дан Даскалеску