Что делать, если сайт на WordPress грузится медленно? Ответ на самом деле прост – настрой кеширование. Можно ещё заниматься оптимизацией изображений, настройкой lazy loading и прочими хитростями. Но кеширование всё равно остаётся ключевым способом ускорения любого сайта на Вордпресс. Кажется, всё просто, зайди в Google, напиши "WordPress cache", найди статью, где больше всего картинок, скачай упомянутый в статье плагин и выстави настройки согласно скриншотам. При любом раскладе твой сайт сразу начнет работать в разы быстрей.
Но дьявол, как обычно, кроется в деталях. В интернете есть самые разные обзоры и сравнения плагинов кеширования. И за столько лет кто-то же должен был выдать идеальный рецепт? Но нет. Все эти обзоры сводятся к тезису: «мы сделали 10 одинаковых сайтов, установили плагины с дефолтными настройками и смотрим, где страница загрузилась быстрее». При этом все забывают, что нюансов при оптимизации кеширования вагон и маленькая тележка. Похоже, эта статья первая, которая примет во внимание реальное поведение пользователей на сайте, вместо сравнения скорости загрузки одной страницы в тепличных условиях.
Используя бестселлеры с Themeforest или, те же конструкторы, вроде Elementor, WP Backery и прочие, сайт обречен на 5-15 секунд TTFB (time for first byte, время ответа сайта) при загрузке КАЖДОЙ страницы. С одной страницы может быть несколько сотен обращений к базе данных, выполняться большое число php-функций, подключаться множество библиотек. Естественно, что такая скорость недопустима, она влечет за собой понижение в поисковой выдаче, "отказы" посетителей, сливы бюджетов на рекламу и так далее. С этим нужно что-то делать.
Я никогда шибко оптимизацией WordPress не заморачивался, потому что в моей практике сайты, которые требуют космической скорости работы, делали не на WordPress, а на Yii2 или Laravel. Для WP я использовал околодефолтные настройки плагина WP Super Cache, подсмотренные на Stackoverflow. Правда со временем начали появляться проблемы. Что-то приходилось «колхозить», где-то пробовать другие плагины. Но каждый раз появлялись всё новые и новые «косяки».
В какой-то момент я просто устал от постоянного «колхозинга» и решил найти идеальное решение. Я занимался этим больше месяца, тестируя разные плагины, разные настройки на разных сайтах, чтобы найти идеальный рецепт.
В статье речь пойдёт о собственных наблюдениях, об особенностях каждого плагина для кеширования WordPress, о том, что заявлено, а что имеем по факту, и конечно, подборе идеальных настроек и устранении проблем. Материала получилось много, на 21 страницу, поэтому я решил разделить его на две части. Первая будет посвящена обзору и выводам, так сказать «для гуманитариев». Во второй части будут приведены настройки и доработки плагинов, а также более подробное пояснение их работы, так сказать «для технарей».
Забегая вперед, скажу, что идеального рецепта (идеальных настроек) не существует. В первую очередь необходимо четко сформулировать свои требования к функционалу и понять принципы работы того или иного плагина. Этим мы сегодня и займемся.
1. Определяем требования к функционалу
Мои требования к функционалу соответствуют классическому многостраничному корпоративному сайту с посещаемостью от 100 до 10 000 чел. в день, со своим блогом, на который ведётся реклама с UTM-метками. Также я делаю большой акцент на автоматизацию, чтобы не приходилось заниматься постоянными доработками и настроить кеширование можно было без особых усилий.
Автокеширование. Сайты приходится периодически обновлять, выкладывать новости, менять текст, картинки и т.д. Кеш-копия страниц в этом случае хранится определённое время, а после обновления страниц сайта необходимо заново создавать кеш-файлы. В этом случае часть пользователей, ровно, как и поисковых роботов, будут видеть насколько долго загружаются некоторые страницы сайта. Чтобы этого избежать, плагины предлагают механизм автоматического кеширования. В этом случае плагин самостоятельно производит обход сайта и сам создает закешированные копии страниц. Важно, чтобы этот механизм у плагина работал без сбоев.
Игнорирование части запросов URL-адреса. Большинство рекламщиков используют для отслеживания эффективности своих рекламных кампаний UTM-метки (или другие GET-параметры). В этом случае они добавляют в адрес страницы ряд запросов, которые никак не влияют на логику работы сайта. Например, у нас есть страница товара, который мы рекламируем: https://www.site.com/landing-page/, но пользователь, перешедший на неё из рекламы, увидит адрес следующего формата: https://www.site.com/landing-page/?utm_source=yandex&utm_medium=cpc&utm_campaign=promo&utm_content=banner&utm_term=i-wan-to-buy-something&yclid=93473892748392743473829.
Естественно, сайт о существовании этой страницы даже не догадывается, и кэш под неё не существует. Он будет создан в момент перехода пользователя по этой длинной ссылке. Но даже, если рекламщик не будет добавлять UTM-метки, то Яндекс Директ, Google Ads или иные рекламные системы будут подставлять свои метки для отслеживания (например, yclid, gclid). Значения таких меток будут всегда разными, соответственно, сайт будет воспринимать их как абсолютно разные страницы. В итоге, мы получаем ситуацию, когда каждый пользователь, привлеченный с помощью рекламы, видит, насколько медленно работает сайт, а хранилище кеша пухнет от кучи мусорных файлов, которые никогда больше не будут задействованы.
Поэтому, плагин кеширования должен учитывать существование некоторых GET-параметров, которые необходимо исключать из URL-адреса страницы при попытке найти подходящий кеш-файл или же создать новый.Возможность использования PHP-функций. Это может прозвучать странно, ведь само по себе кеширование подразумевает предотвращение исполнения PHP-скриптов или работу с БД, но только не в моём случае.
В своё время на разных проектах я неоднократно сталкивался с проблемами стандартных систем аналитики, основанных на JavaScript, таких как Яндекс Метирка или Google Analytics, при анализе лидов. Та же Метрика попросту не видит части заявок, данные отображает в обезличенном виде и с задержкой. Каждый второй научился устанавливать AdBlock, который не передаёт в Метрику JavaScript-события и вырезает прочие скрипты с сайтов. Более того, оказалось, у части пользователей с мобильных устройств не работает JavaScript, который необходим для корректной работы Метрики. Как итог, мы имеем статистику с определённой погрешностью.
Поэтому я сделал свою кастомную систему для аналитики заявок на сайте, которая работает через PHP, а не через JavaScript и не позволяет никаким данным потеряться. И именно здесь появляются проблемы, когда большинство кеширующих плагинов не позволяет при первом визите пользователя запустить нужный PHP-код, который сохранит полную информацию об источнике и характеристиках визита.
2. Разбираем самые популярные плагины кеширования
Как я уже говорил выше, идеального рецепта не существует, и необходимо разобраться в логике работы того или иного плагина и выбрать наиболее подходящее решение для каждого конкретного сайта. Во второй части статьи я подробнее рассматриваю популярные плагины для кеширования WordPress, их проблемы и предлагаю методы решения этих проблем. Здесь я обобщу все плюсы и минусы каждого из плагинов.
При рассмотрении плагинов ниже будут применяться следующие обозначения:
[?] - проблему можно устранить, вмешавшись в исходный код плагина или с помощью внешних сервисов;
[!] - проблему устранить невозможно;
* - замеры скорости довольно субъективны, тем не менее, для наглядности был взят конкретный сайт, скорость загрузки которого составляет ~3 сек без кеширования. Каждый замер проводился по 100 раз, а результаты представлены усредненные. "Скорость загрузки" - это TTFB ("Время до первого байта").
WP Super Cache
Плюсы:
Плагин совершенно бесплатный.
Плагин может работать как в режиме mod_rewrite, так и в режиме PHP. Режим работы PHP-based позволяет исполнять PHP-скрипты в том числе на закешированных страницах.
Быстрая скорость загрузки закешированных страниц: 30-40 мс* в режиме mod_rewrite, 60-80 мс в режиме PHP.
Работа плагина не нагружает сайт, пока происходит кеширование.
Процесс автоматического фонового кеширования сайта работает стабильно.
Автоматическое фоновое кеширование не очищает сразу все файлы, давая возможность быстро получать старые кеш-копии страниц, в то время как новые еще генерируются.
Простая настройка.
Минусы:
[?] Плагин не умеет игнорировать GET-параметры в URL-адресах, в том числе массово распространенные (такие как UTM-метки, gclid, yclid и подобные), поэтому при переходе из рекламы посетители видят долгую загрузку страницы. Для решения этой проблемы требуется внесение изменений в исходный код плагина при установке, а также при каждом обновлении этого плагина.
[?] Для страниц, которые содержат GET-параметры в URL-адресе, плагин создает отдельные кеш-файлы. Доработки плагина позволяют использовать 1 дополнительный кеш-файл конкретной страницы для быстрой её загрузки с любыми вариациями GET-параметров, которые мы указали в предыдущем пункте. Таким образом, создав кеш-копию для страницы example.com/my-page/?utm_source=yandex - эта же страница, но с другим набором GET-параметров (например, example.com/my-page/?utm_source=google&gclid=123) будет загружаться моментально у любого посетителя. Тем не менее, при следующем запуске автоматического кеширования будут удалены все кеш-копии страниц (в т.ч. дополнительные, содержащие GET-параметры), плагин создаст новые кеш-копии обычных страниц, но не дополнительные. Дополнительные кеш-копии страниц, содержащие GET-параметры в URL-адресе будут генерироваться посетителями. Первые посетители будут видеть медленную скорость загрузки таких страниц (например, переходя по рекламе). Исправить это можно отключив автоматическое кеширование - такой способ подойдет для сайтов, на которых редко вносятся изменения. Другой способ решения этой проблемы - реализация механизма, который будет производить обход сайта, согласно sitemap.xml, добавляя к каждому URL любой GET-параметр (например, utm_source=cache_update). Опять же это требует дополнительных идей, как решить данную проблему, а значит дополнительного времени. Можно просто смирится, что у некоторых пользователей с рекламы страницы будут загружаться медленно, но при большом количестве страниц, регулярном обновлении сайта и рекламе, проблема становится критичной.
WP Fastest Cache
Плюсы:
Бесплатная версия полностью покрывает весь функционал, который требуется от плагина кеширования.
Быстрая скорость загрузки закешированных страниц (30-40 мс*);
Работа плагина не нагружает сайт, пока происходит кеширование.
Процесс автоматического фонового кеширования сайта работает стабильно;
Автоматическое фоновое кеширование не очищает сразу все файлы, давая возможность быстро получать старые кеш-копии страниц, в то время как новые еще генерируются.
Плагин позволяет учитывать рекламные GET-параметры в адресной строке (такие как UTM-метки и gclid). Это позволяет моментально отдать пользователю уже существующую кеш-копию страницы без GET-параметров.
Плагин имеет функционал в том числе для оптимизации контента на сайте: минификация HTML/CSS/JS, объединение CSS и JS-файлов, Lazy loading изображений.
Минусы:
[?] Для исключения GET-параметров, не "зашитых" в плагине (таких как yclid) требуется внесение изменений в плагин при установке, а также при каждом обновлении этого плагина.
[?] Плагин работает исключительно с помощью mod_rewrite, поэтому для исполнения PHP-скриптов на закешированных страницах необходимо произвести доработку веб-сайта.
[!] Страницы с GET-параметрами загружаются медленней, чем страницы без них. Так, например, сайт на котором страницы без кеширования загружаются за ~3 сек., с использованием WP Fastest Cache страница загружается за 30-40 мс*, но, если у страницы есть GET-параметры, её кеш-копия будет загружена за 400-500 мс. (для сравнения, скорость загрузки страниц, содержащих GET-параметры при использовании WP Super Cache: 60-80 мс*). Это не то что бы сильная проблема, если сравнивать со скоростью загрузки страниц без использования кеширующих плагинов, но об этом стоит упомянуть.
W3 Total Cache
Плюсы:
Плагин может работать как в режиме mod_rewrite, так и в режиме PHP. Режим работы PHP-based позволяет исполнять PHP-скрипты на закешированных страницах.
Плагин позволяет указать произвольный перечень GET-параметров, которые необходимо игнорировать при обработке запроса.
Феноменальная скорость загрузки страниц: 25-30 мс* в режиме mod_rewrite, 30-40 мс* в режиме PHP-based.
Феноменальная скорость загрузки страниц с GET-параметрами: 30-40 мс* в режиме mod_rewrite, 40-50 мс* в режиме PHP-based.
Плагин имеет функционал для оптимизации контента на сайте: минификация HTML/CSS/JS, объединение CSS и JS-файлов, Lazy loading изображений.
Не требует вмешательства в исходный код плагина.
Минусы:
[!] Автоматическое фоновое кеширование не обновляет кеш-файлы до тех пор, пока срок жизни кеш-файлов не истек. Это приводит к ситуации, при которой кеш-файлы уже очищены, а автоматическое кеширование довольно долго создает новые. И в этот промежуток времени посетители могут увидеть долгие загрузки. Особенно если сайт большой, а обновление поставлено раз в полчаса, то автокеширование может происходить в течение 10 минут, и всё это время пользователи будут видеть долгую загрузку части страниц. При этом во время проведения автокеширования скорость загрузки незакешированных страниц падает с 3 сек до 5-6 сек, т.к. сам плагин нагружает сайт.
[!] Периодически, даже закешированные страницы загружаются долго (2 сек - на тестируемом сайте).
Swift perfomance
Плюсы:
Плагин позволяет указать произвольный перечень GET-параметров, которые необходимо игнорировать при обработке запроса.
Плагин может работать как в режиме mod_rewrite, так и в режиме PHP. Режим работы PHP-based позволяет исполнять PHP-скрипты в том числе и на закешированных страницах.
Неплохая скорость загрузки закешированных страниц: 200-300 мс* в режиме PHP, 30-40 мс* в режиме mod_rewrite. При этом скорость загрузки страниц, содержащих GET-параметры в URL-адресе, всё равно будет 200-300 мс*, даже при использовании mod_rewrite.
Плагин имеет функционал для оптимизации контента на сайте: минификация HTML/CSS/JS, объединение CSS и JS-файлов, Lazy loading изображений, а также оптимизация и сжатие изображений.
Автоматическое фоновое кеширование не очищает сразу все файлы, давая возможность быстро получать старые кеш-копии страниц, в то время как новые еще генерируются (но не всё так просто, смотрим минусы).
Не требует вмешательства в исходный код плагина.
Минусы:
[!] Отсутствие поддержки кириллицы в URL-адресах при кешировании. Swift Perfomance создает кеш ровно по тем адресам, которые имеют страницы сайта, т.е. если у нас URL страницы выглядит как https://example.com/контакты, он не будет переводить "контакты" в URL-encoded для создания кеша. Но браузер будет обращаться именно к https://example.com/%D0%BA%D0%BE%D0%BD%D1%82%D0%B0%D0%BA%D1%82%D1%8B, поэтому страницы, содержащие кириллицу, будут загружаться всегда медленно.
[!] Некорректный механизм ручного обновления кеша. Когда мы обновляем страницу, он моментально генерирует под нее свежий кеш, пользователи не увидят долгих загрузок. Когда мы публикуем новость, она тут же появляется на странице новостей. Но как только эта новость должна попасть куда-то в другое место (например, в сайдбар других страниц), она туда не попадет ровно до тех пор, пока мы полностью вручную не обновим кеш всего сайта или не запустится механизм автокеширования. Когда мы вручную обновляем весь кеш сайта (чтобы наша новость появилась в сайдбаре на всех страницах), далеко не все страницы работают быстро. Через несколько минут после ручного запуска переобхода сайта, часть страниц уже имеют новый кеш (работают быстро), часть страниц еще отдаются со старым кешем (видим, что свежая новость в сайдбарах на этих страницах еще не появилась), но часть страниц (причем, немалая) грузится ужасно долго (8 – 12 сек. против 3-4 сек. без использования кеширования вообще).
[!] Нестабильный механизм автоматического кеширования. При первичных тестах плагин отрабатывает как надо. Но на практике вышло так, что на большинстве сайтов это «умное» автокеширование работает нестабильно. В какой-то момент созданные ранее кеш-файлы просто пропадают, плагин их удаляет или происходит какой-то рассинхрон, хотя новые копии под них ещё не были созданы, и сайт остаётся без какого-либо кеширования. Приходится запускать переобход вручную, а это ведёт к сильной нагрузке на сервер.
[!] Если же выбрать классический вариант обновления кеша (по таймауту) - "Time based mode" - проявятся все те же проблемы как у WP Rocket или W3 Total Cache. Swift Perfomance во время истечения срока жизни кеша сносит все кеш-файлы. Он создает кеш-копии чуть быстрее, чем W3 Total Cache, но все равно в течении 5-7 минут на сайте из 300 страниц посетители увидят медленную загрузку после истечения срока жизни кеш-файлов. Более того, использование мульти-потокового кеширования оказывает довольно ощутимую нагрузку на сервер.
[!] Lite-версия Swift Perfomance вынуждает покупать подписку. В бесплатной версии Swift Perfomance нельзя выбрать высокую скорость для автокеширования, а также отсутствует возможность указать GET-параметры для исключения из URL-адреса при кэшировании.
В ходе своего исследования я также успел поработать с WP Rocket и LiteSpeed Cache, в которых разочаровался почти сразу и не посчитал нужным расписывать подробно все их преимущества и недостатки, их я упоминаю во второй части статьи.
3. Заключение
Без сомнения, наиболее высокую скорость загрузки показал плагин W3 Total Cache. Он работает быстро и в классическом режиме, и в режиме PHP, да и страницы с GET‑параметрами загружает быстрее всех. Но для меня критичной стала проблема отсутствия автоматического фонового кеширования, которое бы обновляло файлы кеша, не снося их полностью, а заменяя постепенно. Плагин, конечно, не требует доработок, и имеет все необходимые настройки, но в период обновления кеша, пользователи, попадающие на сайт, видят медленную загрузку, а при большом трафике на сайте это становится критичной проблемой. Его лучше использовать на статичных сайтах без автокеширования.
Большие надежды я возлагал на Swift Perfomance. Он имеет все необходимые настройки, не требует доработок, да и распространяется платно, а ведь платный плагин должен оправдывать вкладываемые в него средства? Но он разочаровал полностью, нестабильные механизмы автокеширования, недоработанный механизм ручного обновления кеша, высокая нагрузка на сервер при кешировании – все эти недостатки свели на нет его преимущества. Если бы я регулярно не мониторил его работу, может быть и не заметил бы этих недостатков. На текущий момент я его не использую ни на одном из проектов.
WP Super Cache был бы идеальным вариантом, если только на сайты с ним не вести рекламу. Как только на сайте появляются любые GET-параметры, необходимо дорабатывать исходный код плагина, чтобы устранить эту проблему. А при частом обновлении сайта с большим количеством страниц это становится настоящим геморроем, ведь если мы не хотим, чтобы некоторая часть пользователей с рекламы видела медленную загрузку после проведения автокеширования, то необходимо придумывать дополнительные методы обхода страниц с GET-параметрами. Чаще проще установить плагин, который всё это умеет из коробки. К недостаткам WP Super Cache можно также отнести отсутствие работы с оптимизацией контента на сайте (минификация HTML/CSS/JS, объединение CSS и JS-файлов, Lazy loading изображений, а также оптимизация и сжатие изображений), но это на любителя, плагин кеширования по факту не должен этим заниматься, все эти настройки нужно тестить, у других плагинов не все они работают адекватно.
Закрывает эти проблемы плагин WP Fastest Cache, который прекрасно умеет работать с GET-параметрами. Хотя он всё равно требует доработок. Лично мне не сложно внести небольшие изменения в код плагина, чтобы познакомить его с метками типа yclid и разрешить использовать PHP.
Вот и получается, что идеального рецепта не существует. Понимая проблемы плагинов и разобравшись в настройках из второй части статьи, каждый сам сможет подобрать себе плагин под конкретный тип сайта. Мои же рекомендации, следующие:
Рекомендации
На сайтах, на которых почти никогда не вносятся изменения (например, лендингах), рекомендую использовать W3 Total Cache без автокеширования, т.к. он показывает самую высокую скорость загрузки, отлично будет работать с рекламой и не требует доработок. Правда, если уж пришлось внести изменения на статичный сайт, нужно не забыть вручную обновить кеш.
На сайтах, где изменения вносятся часто (например, корпоративных сайтах), рекомендую использовать WP Fastest Cache, он отлично работает с фоновым автокешированием и GET-параметрами, правда не со всеми. Чтобы вести рекламу на сайт, например, из Яндекса, необходимо внести небольшое изменение в исходный код, т.к. плагин не знает метку yclid.
Если на сайт точно не планируется вести рекламу или загружать какие-либо страницы с GET-параметрами (например, блог), то можно использовать и WP Super Cache, и WP Fastest Cache, кому как удобней. WP Super Cache настроить чуть проще и быстрей.
Мне на практике для некоторых сайтов приходится использовать PHP-скрипты, с которым WP Fastest Cache работает только после доработки исходного кода. Здесь часто спасает WP Super Cache, который умеет работать с PHP из коробки. Правда всё ломается, как только на сайте появляется реклама с UTM-метками. WP Super Cache был бы универсальным кешером, если бы разработчики плагина догадались подружить его с GET-параметрами, а сейчас для этого приходится вносить изменения в исходный код плагина и придумывать варианты обхода страниц с GET-параметрами при автокешировании. Об этом нужно всегда помнить.
Если очень хочется вести рекламу на сайт, но очень не хочется дорабатывать плагины, то можно использовать W3 Total Cache с автокешированием и мириться с временной медленной загрузкой сайта в период обновления кеша. А также помнить, что чем больше страниц на сайте и выше трафик, тем выше шанс, что большое количество пользователей увидит медленную загрузку.
Подробные настройки каждого плагина и инструкции по доработке исходного кода я выложу во второй части статьи.
PS
Это переписанная и структурированная статья из моего телеграм-канала «digital на минималках», где я делюсь опытом в бизнесе, инструкциями, рассказываю, как удешевить свои вложения в digital, рассуждаю на небанальные темы, немного бомблю и делюсь мемчиками (осторожно, нецензурная речь). Решил, что подобное объемное исследование будет интересно не только подписчикам моего канала.