WordPress тормозит редко из-за самого ядра. Обычно время ответа съедают десятки плагинов, каждый из которых грузит свои скрипты, стили и запросы к базе. Лечить это установкой ещё пяти «ускоряющих» плагинов — путь в противоположную сторону. Кэширование лучше строить на уровне сервера: OPcache для PHP, страничный кэш в nginx, один объектный кэш и аккуратная работа с базой. Ниже — схема без плагинов-бомб, которую можно проверить на любом LEMP-сервере.

Сначала измерьте, потом ускоряйте

Без замеров легко оптимизировать не то. Отделите сеть и TLS от времени генерации страницы.

curl -s -o /dev/null -w "dns=%{time_namelookup} connect=%{time_connect} ttfb=%{time_starttransfer} total=%{time_total}\n" https://example.ru/
wp db size --path=/var/www/example.ru --tables
wp plugin list --status=active --path=/var/www/example.ru
wp core version --path=/var/www/example.ru

Если ttfb превышает 600–800 мс, узкое место почти наверняка в PHP или базе, а не в канале. Список активных плагинов покажет, сколько кода выполняется на каждом запросе. Правило простое: плагин, который не используется, выключают, а не «оптимизируют».

OPcache: самый дешёвый выигрыш

OPcache хранит скомпилированный байткод PHP в памяти и снимает повторную компиляцию. На типичном сайте это даёт заметный прирост без единой строки в шаблонах.

opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.revalidate_freq=0

Настройки кладут в /etc/php/8.4/fpm/conf.d/99-opcache.ini или аналогичный файл вашей версии PHP. validate_timestamps=0 означает, что PHP не проверяет изменения файлов на каждом запросе. После деплоя обязательно перезагрузите FPM, иначе сайт будет работать на старом коде.

php-fpm8.4 -i | grep -E "opcache.(enable|memory_consumption|max_accelerated_files)"
sudo systemctl reload php8.4-fpm
sudo systemctl status php8.4-fpm --no-pager

Проверяйте именно FPM, а не CLI: у них отдельные конфигурации и разные кэши. Если opcache.enable в выводе равен Off, модуль не подключён или файл настроек лежит не в том каталоге.

Страничный кэш на стороне nginx

Готовый HTML можно отдавать без запуска PHP. Это самый большой выигрыш для сайта с преобладанием анонимных посетителей. В http-блок описывают зону кэша и ключ, а каталог /var/cache/nginx/wp создают заранее и передают nginx.

fastcgi_cache_path /var/cache/nginx/wp levels=1:2 keys_zone=wp:100m inactive=60m max_size=2g;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
map $http_cookie $skip_cache {
    default 0;
    ~*wordpress_logged_in 1;
    ~*wp-postpass 1;
    ~*comment_author 1;
    ~*woocommerce_items_in_cart 1;
}
map $request_method $skip_method {
    default 1;
    GET 0;
    HEAD 0;
}
map $request_uri $skip_uri {
    default 0;
    ~*^/(wp-admin|wp-login\.php|wp-cron\.php|xmlrpc\.php) 1;
}

Карта $skip_cache исключает авторизованных пользователей, комментаторов и корзину магазина. Второй map не даёт кэшировать POST-запросы, третий закрывает админку, вход, cron и XML-RPC. В блоке location ~ \.php$ остаётся подключить зону и добавить диагностический заголовок.

fastcgi_cache wp;
fastcgi_cache_valid 200 301 302 10m;
fastcgi_cache_use_stale error timeout updating http_500 http_503;
fastcgi_cache_lock on;
fastcgi_cache_bypass $skip_cache $skip_method $skip_uri;
fastcgi_no_cache $skip_cache $skip_method $skip_uri;
add_header X-FastCGI-Cache $upstream_cache_status;

Заголовок X-FastCGI-Cache покажет HIT, MISS или BYPASS. Ответы с Set-Cookie nginx по умолчанию не кэширует — не отключайте это поведение без понимания последствий. Штатный nginx не умеет точечно сбрасывать кэш: либо короткий TTL, либо модуль ngx_cache_purge из сторонней сборки, либо очистка каталога вручную.

sudo nginx -t
sudo systemctl reload nginx
curl -sI https://example.ru/ | grep -i x-fastcgi-cache
sudo find /var/cache/nginx/wp -type f -delete

Объектный кэш и транзиенты

Страничный кэш не помогает авторизованным пользователям и динамическим блокам. Здесь нужен объектный кэш: Redis или Valkey плюс один drop-in object-cache.php. Это не «плагин-бомба», а один слой, который заменяет обращения к базе чтением из памяти. На практике ставят пакет redis-server или valkey, расширение php-redis и drop-in, затем проверяют работу через WP-CLI и журнал PHP.

wp cache flush --path=/var/www/example.ru
wp transient delete --expired --path=/var/www/example.ru
wp option list --autoload=on --format=total_bytes --path=/var/www/example.ru
wp db optimize --path=/var/www/example.ru

Просроченные транзиенты и раздутые автозагружаемые опции — типичная причина медленных запросов. Третья команда показывает суммарный размер автозагружаемых опций в байтах, четвёртая оптимизирует таблицы. Если размер превышает несколько мегабайт, ищите плагин, который пишет в autoload на каждом запросе.

База, ревизии и WP-Cron

Ревизии записей незаметно раздувают таблицу wp_posts. Ограничьте их в wp-config.php и удалите лишнее через WP-CLI.

define('WP_POST_REVISIONS', 5);
define('DISABLE_WP_CRON', true);
wp post delete $(wp post list --post_type=revision --format=ids) --force
wp cron event run --due-now --path=/var/www/example.ru

DISABLE_WP_CRON отключает запуск задач при посещениях и переносит их в системный cron. Это снимает лишнюю нагрузку с PHP-FPM, но требует настоящего планировщика.

*/5 * * * * cd /var/www/example.ru && /usr/bin/wp cron event run --due-now --path=/var/www/example.ru >> /var/log/wp-cron.log 2>&1
wp cron event list --path=/var/www/example.ru

Перед удалением ревизий сделайте резервную копию базы. Массовое удаление необратимо, а --force обходит корзину.

Статика, сжатие и заголовки

Последний слой — правильные заголовки для файлов, которые не меняются. Их отдаёт nginx, не пропуская запрос через PHP.

gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
location ~* \.(css|js|jpg|jpeg|png|webp|avif|svg|woff2)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    access_log off;
}

immutable уместен только для файлов с версией в имени: иначе браузер не увидит обновлённый стиль до истечения срока. Для HTML ставьте короткий Cache-Control или не задавайте его вовсе. Проверьте, что nginx отдаёт сжатые версии: curl -sI -H "Accept-Encoding: gzip" https://example.ru/style.css | grep -i content-encoding.

Порядок внедрения и чек-лист

  • Снимите замеры TTFB и список активных плагинов до изменений.
  • Включите OPcache и перезагрузите FPM, проверьте ответ сайта.
  • Добавьте страничный кэш с обходом для авторизованных и POST.
  • Подключите один объектный кэш, очистите просроченные транзиенты.
  • Ограничьте ревизии и перенесите WP-Cron в системный планировщик.
  • Настройте статику и сжатие, повторите замеры и сравните результат.

После каждого шага проверяйте вход в админку, оформление заказа и комментарии. Кэш, который ломает авторизацию, хуже отсутствия кэша. Держите простой способ отключения: убрать несколько строк из конфигурации nginx и перезагрузить сервис.

Итог

Ускорение WordPress без плагинов-бомб — это четыре независимых слоя: OPcache, страничный кэш nginx, объектный кэш и гигиена базы. Каждый даёт понятный эффект и легко откатывается. Начните с замеров и OPcache, затем добавьте кэш HTML с аккуратными исключениями, а плагины оставьте только те, без которых сайт действительно не работает.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте