В рамках моих усилий по ускорению моих тем для моих клиентов я доставляю свой CSS через динамический файл PHP. В конце вызова, например my_theme_css.php
:
Это позволяет мне добавлять заголовки Expiry в мой CSS и JavaScript следующим образом:
<?php
header("Expires: Thu, 31 Dec 2020 20:00:00 GMT");
header('Content-type: text/css');
?>
Затем я хочу разрешить пользователю добавлять свой собственный CSS, поэтому я установил следующее:
<?php
header("Expires: Thu, 31 Dec 2020 20:00:00 GMT");
header('Content-type: text/css');
?>
p{color:blue;}
/** Custom CSS **/
<?php
if(get_theme_mod('my_custom_css') != '') {
$my_custom_css = get_theme_mod('my_custom_css');
echo $my_custom_css;
}
?>
Затем я добавил применимые параметры темы. Но я обнаружил, что get_theme_mod()
это не работает из-за проблемы с областью действия (я думаю). Любые предложения о том, как обойти это?
Я мог бы добавить следующий код:
<?php
if(get_theme_mod('my_custom_css') != '') {
$my_custom_css = get_theme_mod('my_custom_css');
echo $my_custom_css;
}
?>
Внутри <style></style>
тегов в заголовке, и это будет работать нормально, ожидайте, что я не хочу встроенный CSS, я хочу, чтобы он был в основном файле CSS с заголовком истечения срока действия.
Разве статический файл css не будет лучше для производительности? Есть также несколько хороших советов, которые я получил по аналогичному вопросу, который я задал.
@Chris_O Если бы это было для нескольких правил стиля, я бы сказал «да», но для более интенсивного использования это означает, что 100 дополнительных строк загружаются каждый раз, когда загружается страница, по сравнению с одной внешней таблицей стилей с датой истечения срока действия в далеком будущем, которую можно кэшировать.
@Ash G: предоставьте статический файл CSS и правильно настройте кэширование на веб-сервере. Это мое предложение.
@hakre Это будет использоваться в тех случаях, когда доступ на этом уровне на сервере недоступен или когда конечный пользователь недостаточно осведомлен для внесения этих изменений. По этой причине код должен быть на уровне темы.
@Ash G: Если это так, то это полагается на PHP, верно.
Привет Майк, спасибо за это. Вы всегда даете такие превосходные ответы! Я пытался избежать всего этого wp_load ( ottopress.com/2010/dont-include-wp-load-please )
@Ash G: хех. Вот почему твой не работал! 😉
get_theme_mod()
является частью WordPress API, так что без/wp-load.php
вас его не получить! И API не модульный, все или ничего. Но я буду спорить, хотя Отто прав, в целом это не большая проблема, если вы кэшируете в течение 24 часов или дольше с помощьюExpires
илиCache-Control
. И если вы действительно хотите оптимизировать, вы можете удалить/wp-load.php
и использовать необработанные вызовы MySQL для заменыget_theme_mod()
функции, если хотите; это тривиальный код, единственным недостатком которого является то, что он нарушает инкапсуляцию API деталей хранилища модов темы.@Ash G: Конечно, всегда есть последняя часть моего ответа, которую я начал с «В любом случае, это может быть излишеством!» … 🙂
@AshG : О, и спасибо за комплимент. Я лучше всего учусь, обучая других, и я пытаюсь стать экспертом во всем, что нужно знать о кодировании для WordPress, поэтому я прилагаю усилия к ответам. Помощь другим помогает мне; это хороший беспроигрышный вариант, не так ли? 🙂
Привет @Ash G : Ну, вы могли бы использовать
file_get_contents()
и сканировать в/wp-config.php
поисках$table_prefix
иDB_HOST
,DB_NAME
,DB_USER
иDB_PASSWORD
; это не было бы ни сложным кодом для написания, ни кодом со слишком большими накладными расходами (по сравнению со всеми/wp-load.php
) Очки для размышления. 🙂 И спасибо за выбор и голосование.Спасибо за помощь. Однако это не работает. Я не понимаю, почему это обойдет проблему масштаба?
Я не понимаю, почему вообще может возникнуть проблема с областью действия функции. Но я подумал, что продемонстрирую, как подобные задачи выполняются в других плагинах.
Привет @Ash G:
Я не следил на 100% за тем, где у вас конкретно возникали проблемы, поэтому я не уверен, что действительно могу ответить на ваши вопросы по пунктам, но я могу объяснить, как это сделать с нуля. И если то, что вы делаете, не намного сложнее, чем вы упомянули, это немного больше работы, чем я думаю, вы ожидали, но это все еще вполне выполнимо. И даже если я освещаю много тем, которые вы уже знаете, есть большая вероятность, что другие люди с меньшими знаниями или опытом найдут это через Google и им тоже помогут.
Загрузить WordPress с помощью
/wp-load.php
Первое, что нам нужно сделать в вашем
my_theme_css.php
файле, это загрузить функции основной библиотеки WordPress. Следующая строка кода загружает/wp-load.php
. Он используется$_SERVER['DOCUMENT_ROOT']
для поиска корня веб-сайта, поэтому вам не нужно беспокоиться о том, где вы храните этот файл на своем сервере; предполагаяDOCUMENT_ROOT
, что он установлен правильно, как всегда должно быть для WordPress, тогда это загрузит WordPress:Так что это легкая часть. Далее идет сложная часть…
PHP-скрипты должны обрабатывать всю логику кэширования
Держу пари, здесь вы могли споткнуться, потому что я точно споткнулся, когда пытался понять, как ответить на ваш вопрос. Мы настолько привыкли к деталям кэширования, которые обрабатываются веб-сервером Apache, что забываем или даже не осознаем , что должны сами выполнять всю тяжелую работу, когда загружаем CSS или JS с PHP.
Конечно, заголовок срока действия может быть всем, что нам нужно, когда у нас есть прокси посередине, но если запрос доходит до веб-сервера, а PHP-скрипт волей-неволей возвращает содержимое и код состояния «ОК», по сути, вы не имеют кэширования.
Возврат «200 OK» или «304 Not Modified»
В частности, наш файл PHP, который возвращает CSS, должен правильно реагировать на заголовки запроса, отправленные браузером. Наш PHP-скрипт должен возвращать правильный код состояния в зависимости от содержания этих заголовков. Если содержимое должно быть предоставлено, потому что это первый запрос или срок действия содержимого истек, скрипт PHP должен сгенерировать весь контент CSS и вернуться с «200 Ok».
С другой стороны, если мы определяем на основе заголовков запросов, связанных с кешем, что клиентский браузер уже имеет последнюю версию CSS, мы не должны возвращать какой-либо CSS и вместо этого возвращать «304 Not Modified». Слишком много строк кода для этого соответственно (конечно, вы никогда не будете использовать их одну за другой, я показываю это здесь только для удобства) :
Четыре разновидности кэширования HTTP
Далее нам нужно рассмотреть различные способы, которыми HTTP может обрабатывать кэширование. Первое — это то, что вы упомянули;
Expires
:Expires
заголовок ожидает дату в формате ( функция PHPgmdate()
)'D, d M Y H:i:s'
с' GMT'
добавлением ( GMT означает среднее время по Гринвичу ). Теоретически, если этот заголовок обслуживается, браузер и нижестоящие прокси-серверы будут кэшироваться до тех пор, пока не пройдет указанное время, после чего он запустится. повторный запрос страницы. Это, вероятно, самый известный из кэширующих заголовков, но явно не самый предпочтительный для использования; Cache-Control лучше. Интересно, что в моем тестированииlocalhost
с Safari 5.0 на Mac OS XI так и не удалось заставить браузер учитыватьExpires
заголовок; это всегдаснова запросил файл (если кто-то может объяснить это, я был бы признателен). Вот пример, который вы привели выше:Cache-Control
с заголовком легче работать, чем сExpires
заголовком, потому что вам нужно только указать количество времени в секундах, чтоmax-age
означает, что вам не нужно придумывать точный формат даты в строковой форме, которую легко ошибиться.. Кроме тогоCache-Control
, позволяет несколько других опций, таких как возможность указать клиенту всегда повторно проверять кеш с помощью этойmustrevalidate
опции иpublic
когда вы хотите принудительно кешировать обычно не кешируемые запросы (т. е. запросы черезHTTPS
) и даже не кешировать, если это то, что вам нужно (т. е. вы можете заставить.GIF отслеживания рекламы размером 1×1 пиксель не кэшироваться.) Как будтоExpires
я также не смог заставить это работать при тестировании ( любая помощь?) Следующий пример кэширует 24-часовой период (60 секунд на 60 минут на 24 часа):Last-Modified
ответа и заголовкаModified-Since
Они также используют тот же формат даты по Гринвичу, что иExpires
заголовок, но они выполняют рукопожатие между клиентом и сервером. PHP-скрипт должен отправитьLast-Modified
заголовок (который, кстати, вы должны обновлять только тогда, когда ваш пользователь в последний раз обновляет свой пользовательский CSS), после чего браузер продолжит отправлять то же значение обратно в качествеIf-Modified-Since
заголовка, и за это отвечает PHP-скрипт. сравнить сохраненное значение с отправленным браузером. Здесь PHP-скрипт должен принять решение между обслуживанием200 Ok
файла304 Not Modified
. Вот пример подачиLast-Modified
заголовка с использованием текущего времени (которое нечто мы хотим сделать; см. более поздний пример того, что нам действительно нужно):А вот как вы читаете
Last-Modified
возвращаемое браузером черезIf-Modified-Since
заголовок:ETag
ответа и заголовкаIf-None-Match
запроса. НаETag
самом деле это просто токен, который наш PHP устанавливает для него уникальное значение (обычно основанное на текущей дате) и отправляет в браузер, а браузер возвращает его. Если текущее значение отличается от того, что возвращает браузер, ваш PHP-скрипт должен регенерировать контент, сервер в200 Ok
противном случае ничего не генерирует и обслуживает304 Not Modified
. Вот пример установки сETag
использованием текущего времени:А вот как вы читаете
ETag
возвращаемое браузером черезIf-None-Match
заголовок:Теперь, когда мы рассмотрели все это, давайте посмотрим на фактический код, который нам нужен:
Обслуживание файла CSS через
init
иwp_enqueue_style()
Вы этого не показали, но я решил показать это на благо других. Вот вызов функции, который сообщает WordPress использовать
my_theme_css.php
CSS. Это можно сохранить вfunctions.php
файле темы или даже в плагине, если это необходимо:Следует отметить несколько моментов:
is_admin()
чтобы избежать загрузки CSS в админке (если вы этого не хотите…),get_theme_mod()
для загрузки CSS с версией по умолчанию1.00
(подробнее об этом чуть позже),get_stylesheet_directory_uri()
для получения правильного каталога для текущей темы, даже если текущая тема является дочерней темой,wp_enqueue_style()
для постановки CSS в очередь, чтобы позволить WordPress загрузить его в нужное время, где'php-powered-css'
произвольное имя для ссылки в качестве зависимости позже ( при необходимости ), а пустое значениеarray()
означает, что этот CSS не имеет зависимостей ( хотя в реальном мире он часто имел бы один или несколько ), и$version
; Вероятно, самый важный из них — мы советуемwp_enqueue_style()
добавить?ver=1.00
параметр к/my_theme_css.php
URL-адресу, чтобы при изменении версии браузер рассматривал его как совершенно другой URL-адрес (подробнее об этом чуть позже).Настройка
$version
иLast-Modified
когда пользователь обновляет CSSВот в чем хитрость. Каждый раз, когда пользователь обновляет свой CSS, вы хотите обслуживать контент, а не ждать, пока
2020
тайм-аут кеша каждого браузера не истечет, верно? Вот функция, которая в сочетании с моим другим кодом сделает это. Каждый раз, когда вы сохраняете CSS, обновленный пользователем, используйте эту функцию или функциональность, подобную той, что содержится внутри:Функция
set_my_custom_css()
автоматически увеличивает текущую версию на 0,01 (это было просто произвольное значение приращения, которое я выбрал), а также устанавливает дату последнего изменения прямо сейчас и, наконец, сохраняет новый пользовательский CSS. Чтобы вызвать эту функцию, это может быть так же просто, как это (гдеnew_custom_css
, скорее всего, будет назначено через пользователя$_POST
, а не путем жесткого кодирования, как вы видите здесь) :Что подводит нас к последнему, хотя и важному шагу:
Создание CSS из PHP-скрипта
Наконец мы видим мясо, сам
my_theme_css.php
файл. На высоком уровне он проверяет какIf-Modifed-Since
сохраненноеLast-Modified
значение, так и тоIf-None-Match
,ETag
которое было получено из сохраненногоLast-Modified
значения, и, если ни одно из них не изменилось, просто устанавливает заголовок304 Not Modifed
и ветви до конца.Однако, если какой-либо из них изменился, он генерирует файлы
Expires
,Cache-Control
.Last-Modified
иEtag
заголовки, а также200 Ok
и указывает, что тип контентаtext/css
. Нам, вероятно, все это не нужно, но, учитывая, насколько привередливым может быть кэширование с разными браузерами и прокси, я думаю, что не помешает охватить все основы. (И любой, у кого больше опыта с кэшированием HTTP и WordPress, пожалуйста, отзовитесь, если я ошибаюсь в каких-то нюансах.)В следующем коде есть еще несколько деталей, но я думаю, вы, вероятно, сможете разобраться с ними самостоятельно:
Итак, с этими тремя основными битами кода; 1.)
add_php_powered_css()
функция, вызываемаяinit
хуком, 2.)set_my_custom_css()
функция, вызываемая любым кодом, позволяет пользователю обновлять свой собственный CSS, и, наконец, 3.)my_theme_css.php
вы должны в значительной степени это лизать.Дальнейшее чтение
Помимо тех, которые уже были связаны, я наткнулся на несколько других статей, которые, как мне показалось, были действительно полезными по этому вопросу, поэтому я решил, что должен связать их здесь:
Кэш это! Решить проблемы с производительностью PHP — типичнаяUber-статья SitePoint ; пять (5) длинных страниц, посвященных кэшированию и PHP, включая HTTP и другие формы кэширования.
CSS Caching Hack — это то, что я сделал,
$version
но он объясняет более подробно, чем я.php: как управлять кэшированием страниц — подробные сведения об использовании заголовков HTTP с PHP.
Эпилог:
Но было бы упущением оставить тему без заключительного комментария.
Истекает через
2020
? Наверное, слишком экстремально.Во-первых, я действительно не думаю, что вы хотите установить
Expires
2020 год. Любые браузеры или прокси-серверы, которые уважаютExpires
, не будут повторно запрашивать даже после того, как вы внесли много изменений CSS. Лучше установить что-то разумное, например, 24 часа (как я сделал в своем коде), но даже это расстроит пользователей в течение дня, в течение которого вы вносите изменения в жестко запрограммированный CSS, но забываете указать номер версии. Умеренность во всем?В любом случае, это может быть излишеством!
As I was reading various articles to help me answer your question I came across the following from Mr. Cache Tutorial himself, Mark Nottingham:
Несмотря на то, что весь этот код я написал здорово, и его было весело писать (да, я действительно это признал), может быть, лучше просто генерировать статический файл CSS каждый раз, когда пользователь обновляет свой собственный CSS, и позволить Apache делать всю тяжелую работу. как это было рождено делать? Я просто говорю…
Надеюсь это поможет!
Попробуйте закодировать его так:
Это должно помочь вам обойти любые проблемы с областью действия
get_theme_mod()
функции.