Photo by Souvik Banerjee
Ускоряем сайт на WordPress

Ускоряем сайт на WordPress

10.11.23
4.02.24

Сервис PageSpeed Insights многим не даёт покоя и мы разделяем естественное желание каждого сделать не слишком шуструю CMS WordPress быстрой и с отметками выше 90. С использованием кеш-плагина и правильной настройкой Nginx можно добиться очень высокой скорости.

Будем рассматривать связку Nginx + Apache + WordPress (плагин WP Super Cache). Кеширующий плагин можно использовать и другой, но настройки Nginx будут отличаться. План такой:

  1. Всю статику (картинки, css, js и т.д.) выдаёт Nginx напрямую минуя Apache;
  2. Всю динамику (PHP запросы) Nginx сначала смотрит в кеш и если есть выдаёт напрямую как статическую страницу, а если там нет, то передаёт запрос на Apache;
  3. При отсутствии кэша запросы передаются в Apache. Он формирует ответ и плагин WP Super Cache создаёт кеш страницы, который будет выдан при следующем аналогичным запросе.

И так, приступаем.

Настройка Nginx выдачи статического контента.

В файл конфигурации сайта nginx (обычно это /etc/nginx/site-enabled/your_site) добавляем такой блок:

location ~* ^.+\.(css|js|jpg|jpeg|gif|png|ico|svg|webp)$ {
  expires 400d;
  add_header Pragma public;
  add_header Cache-Control public;
}

Набор файлов (css|js|jpg|jpeg|gif|png|ico|svg|webp) может быть шире, зависит от того что вы используете. Expires (вторая строка) задаёт время жизни кеша для браузера. Google рекомендует устанавливать более чем год. add_header это добавление заголовков к ответу сервера.

Теперь более сложная динамическая часть.

Выдаем кеш через Nginx

Nginx «умеет» выдавать статику очень быстро. Настроим nginx таким образом чтобы он выдавал кеш если он существует, либо пересылал запросы к Apache. Тут основной блок кода следующий:

set $cache_uri $request_uri;
location / {
                try_files /wp-content/cache/supercache/имя-вашего-сайта${cache_uri}index-https.html $uri @fallback;
                default_type   text/html;
}

Тут сохраняем запрос в переменную $cache_uri это нам понадобится позже. Далее, в location / заставляем nginx сначала искать в кеш, затем смотреть абсолютный путь и потом, если ничего нет, посылаем запрос к Apache (@fallback). Не забудьте прописать root до корня вашего сайта.

Прописываем gzip_static если в настройках плагина включили создание сжатого контента. В try_files указываем путь относительно корня сайта директивы root и имя сайта. Плагин WP Super Cache будет создавать статические страницы именно в этой директории. Можете предварительно проверить. Плагин WP Super Cache должен быть уже установлен, там всё просто — не будем на этом останавливаться.

Далее, если кеша нет, то это заставит nginx перейти к следующему варианту ($uri) и если там нет, то к @fallback — у нас это Apache. Его можно прописать следующим образом:

location @fallback {
                proxy_pass http://ваш_сайт_или_localhost:8080;
                include snippets/proxy_params.conf;
}

Тут собственно организовываем передачу запроса к Apache (или к php-fpm в зависимости от того как вы настроили обработку php).

На этом обработка динамического контента закончена. Единственное, надо учесть запрет кеширования в post-запросах и админке вордпресса. Для этого «сбрасываем» переменную $cache_uri в ‘null cache’ (можно любое значение, какую-нибудь ерунду, главное чтобы Nginx не нашёл файл и перешёл к запросу). Вставляем следующий код перед «location /» но после set $cache_uri $request_uri;

if ($request_method = POST) {
    set $cache_uri 'null cache';
}
if ($query_string != "") {
    set $cache_uri 'null cache';
}
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") {
    set $cache_uri 'null cache';
}
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") {
    set $cache_uri 'null cache';
}

Тут мы в POST-запросах, запросах с GET-параметрами (не пустыми) и для запросов к админпанели WordPress заставляем Nginx не находить кеш.

Целиком фрагмент настройки Nginx для работы с кэш WordPress:

set $cache_uri $request_uri;
if ($request_method = POST) {
    set $cache_uri 'null cache';
}
if ($query_string != "") {
    set $cache_uri 'null cache';
}
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") {
    set $cache_uri 'null cache';
}
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") {
    set $cache_uri 'null cache';
}
location ~* ^.+\.(css|js|jpg|jpeg|gif|png|ico|svg|webp)$ {
  expires 400d;
  add_header Pragma public;
  add_header Cache-Control public;
}
location / {
                gzip_static on;
                try_files /wp-content/cache/supercache/имя-вашего-сайта${cache_uri}index-https.html $uri @fallback;
                default_type   text/html;
}
location @fallback {
                proxy_pass http://ваш_сайт_или_localhost:8080;
                include snippets/proxy_params.conf;
}

Как проверить что всё работает правильно.

Для того чтобы понять кто отдаёт нам контент, Nginx ли это или Apache, надо прописать произвольные заголовки. В секцию location / {...} добавить сточку:

add_header x-powered-by 'WP Super Cache + NGinx';

Далее через curl -I ваш_сайт проверить вывод заголовка. Если увидели:

x-powered-by: WP Super Cache + NGinx

то всё работает!