Как ускорить WordPress: что делает каждый слой кэширования
Это руководство разбирает слои кэширования типичного сайта на WordPress сверху вниз: что делает каждый слой, почему некоторые страницы его обходят, в каком порядке всё включать и как проверить результат реальными цифрами. Оно написано для владельцев сайтов и администраторов, которые могут редактировать wp-config.php и выполнить несколько команд по SSH.
Как устроены слои
Запрос к странице WordPress проходит несколько станций: браузер посетителя, веб-сервер с полностраничным кэшем, интерпретатор PHP с OPcache, объектный кэш и, наконец, MySQL. Каждый слой стоит перед следующим, и попадание в верхний слой означает, что всё, что ниже, не выполняет никакой работы. Попадание в полностраничный кэш полностью пропускает PHP и базу данных. Попадание в объектный кэш всё ещё выполняет PHP, но пропускает повторяющиеся запросы к базе. Поэтому слои не взаимозаменяемы: каждый помогает своему типу трафика.
Полностраничный кэш: самый большой выигрыш
Полностраничный кэш сохраняет готовый HTML страницы и отдаёт его следующему посетителю, вообще не запуская WordPress. Для анонимного трафика это самое крупное улучшение из возможных: ответ из кэша занимает несколько миллисекунд вместо нескольких сотен, потому что не выполняется ни PHP, ни один запрос к базе данных.
Страницы вошедших пользователей и корзины обходят этот кэш намеренно. Их HTML персонализирован: панель администратора, имя пользователя, содержимое корзины. Отдача кэшированной копии показала бы одному посетителю данные другого. Поэтому плагины кэширования и правила сервера пропускают кэш, как только видят такие cookie, как wordpress_logged_in_* или woocommerce_cart_hash. Практический вывод: магазин, где большинство покупателей вошли в аккаунт, получает от страничного кэша заметно меньше и сильно зависит от нижних слоёв.
Проверить, отдана ли страница из кэша, можно по заголовкам ответа:
curl -sI https://example.com/ | grep -i -E "x-cache|age|cache-control"
Объектный кэш: что на самом деле экономит Redis
По умолчанию WordPress при каждом запросе заново собирает всё из MySQL: автозагружаемые опции, метаданные пользователей и записей, связи таксономий, настройки плагинов, структуры меню. Большинство этих запросов возвращают один и тот же результат тысячи раз в день. Постоянный объектный кэш хранит эти результаты в памяти Redis, поэтому следующий запрос читает их, не обращаясь к базе данных.
Эффект максимален именно там, где полностраничный кэш бессилен: wp-admin, вошедшие пользователи, оформление заказа в WooCommerce, вызовы REST API. Некэшированный просмотр страницы часто выполняет 100 и более запросов; с прогретым Redis это число падает до нескольких десятков.
wp plugin install redis-cache --activate wp redis enable wp redis status
Если wp redis status показывает соединение и растущее число ключей, всё работает. Типичному сайту нужен скромный объём памяти Redis: обычно достаточно от 64 до 256 МБ.
OPcache: не компилируйте PHP при каждом запросе
PHP перед выполнением компилируется в байткод. Без OPcache интерпретатор перекомпилирует ядро WordPress, тему и все плагины, а это несколько тысяч файлов, при каждом запросе. OPcache держит скомпилированный байткод в общей памяти, поэтому эта цена платится один раз после изменения кода, а не постоянно.
Любая современная сборка PHP включает OPcache, и для веб-сервера он обычно включён. Проверяйте его через веб-SAPI, а не через командную строку: php -r выполняется в CLI, где opcache.enable_cli по умолчанию выключен, поэтому проверка из CLI сообщает false даже тогда, когда в PHP-FPM OPcache работает нормально. Положите временный файл в корень сайта, запросите его по HTTP, затем удалите:
echo ' /var/www/html/opcache-check.php curl -s https://example.com/opcache-check.php rm /var/www/html/opcache-check.php
bool(true) означает, что OPcache активен для реальных веб-запросов. Разумные настройки php.ini для WordPress: opcache.memory_consumption=192 и opcache.max_accelerated_files=20000. Если вы обновляете код копированием файлов, оставьте opcache.validate_timestamps=1, чтобы изменения подхватывались.
Кэширование в браузере и форматы изображений
Дешевле всего обходится запрос, который браузер вообще не отправляет. Статические ресурсы: CSS, JavaScript, шрифты и изображения, стоит кэшировать на стороне клиента надолго. WordPress добавляет к подключаемым ресурсам параметр ?ver=, поэтому долгий срок хранения безопасен: когда файл меняется, меняется и его URL. Типичное правило nginx:
location ~* \.(css|js|png|jpg|jpeg|gif|svg|webp|avif|woff2)$ {
expires 365d;
add_header Cache-Control "public, immutable";
}
Формат изображения значит не меньше, чем его кэширование. WebP обычно на 25 или даже 30 процентов меньше эквивалентного JPEG, а AVIF ещё на 15 или 20 процентов меньше WebP ценой более медленного кодирования. Конвертируйте при загрузке плагином или cron-задачей, сохраняйте оригинал как запасной вариант и не перекодируйте уже оптимизированные файлы: каждое сжатие с потерями снижает качество.
Порядок работ, измерения и миф о пяти плагинах
Включайте слои в таком порядке и измеряйте после каждого шага, а не один раз в конце:
- Проверьте OPcache. Это фундамент, он не несёт риска и не требует плагина.
- Полностраничный кэш. Самый большой выигрыш для анонимного трафика.
- Объектный кэш Redis. Помогает вошедшим пользователям, wp-admin и WooCommerce, то есть трафику, который страничный кэш обслужить не может.
- Кэширование в браузере и заголовки expires.
- WebP или AVIF для изображений.
Следить нужно за TTFB, временем до первого байта, потому что слои кэширования срабатывают до того, как первый байт покидает сервер:
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}s total: %{time_total}s\n" https://example.com/
Выполните команду 5 раз и отбросьте первый результат: он может попасть в холодный кэш. Некэшированная страница WordPress обычно показывает TTFB от 300 до 800 мс; попадание в полностраничный кэш должно оставаться заметно ниже 100 мс.
Наконец, миф: установка пяти плагинов кэширования не даёт пятикратного ускорения. Два страничных кэша отдают устаревшие копии друг друга, двойная минификация ломает JavaScript, а очистка в одном плагине не задевает копию, которую держит другой. Используйте один инструмент на слой и предпочитайте страничный кэш на уровне сервера, а не внутри PHP.
На наших тарифах WordPress хостинга весь этот набор, страничный кэш на уровне сервера, Redis и OPcache, уже настроен, так что из списка выше остаётся только измерение. Если вы хотите настроить всё самостоятельно, те же слои поддерживает любой из наших тарифов хостинга сайтов.
Читайте дальше
Готовы начать?
Запустите за минуты или обсудите с инженером, что подходит вашему проекту.