Кэширование в WordPress часто понимают неправильно. В итоге сайты работают медленнее, чем могли бы. В этой статье я постараюсь развенчать некоторые из существующих заблуждений и внести большую ясность в вопрос кэширования. Надеюсь, к концу этой статьи вы поймете, как разные уровни кэширования участвуют в оптимизации WordPress.
Что такое кэширование и почему оно важно
Кэш – уровень хранения, на котором содержатся временные копии файлов и данных из одного запроса, чтобы последующие запросы могли быстрее получать доступ к этому контенту. В WordPress это может означать что угодно, начиная от кэширования всей страницы и заканчивая результатами запроса к базе данных.
Прежде чем мы углубимся в разные механизмы кэширования, давайте рассмотрим все преимущества этого подхода. Кэширование выполняет две основные задачи:
- Улучшает производительность приложений. Для WP это означает, что сайт будет загружаться быстрее и пользователи получат лучший опыт взаимодействия.
- Увеличивается пропускная способность приложения. Это означает, что ваш сайт сможет обрабатывать больше трафика.
Также кэширование позволяет повысить производительность и пропускную способность приложений без увеличения затрат на хостинг. То есть вам нужно гораздо меньше системных ресурсов (ЦП, память) для размещения сайта, если он был правильно кэширован. Лучшая производительность может быть полезна для SEO, поскольку скорость страниц является одним из факторов ранжирования, используемых поисковыми системами. Это действительно беспроигрышная стратегия (если все настроено грамотно).
Уровни кэширования
WordPress – это CMS с базой данных, т.е. обработка одного запроса задействует довольно много разных участков. В своей стандартной сборке система WP сначала должна будет отправить запрос к БД и сформировать страницу, после чего эта страница уже будет передана пользователю. Это осуществляется при каждом входящем запросе, что крайне неэффективно, особенно когда контент страницы не менялся. Типичный запрос будет выглядеть примерно так:
Как правило, чем больше участков задействовано в обработке запроса, тем дольше пользователь будет ждать ответа, тем больше используется системных ресурсов. Чтобы бороться с этим, к каждому отдельному уровню применяется свое кэширование. В итоге мы имеем три основных уровня:
- Браузерное кэширование.
- Страничное кэширование.
- Объектное кэширование.
Начнем мы с браузерного кэширования.
Браузерное кэширование
Хотя браузерное кэширование и не всегда помогает улучшить время отклика или пропускную способность (особенно в WordPress), оно остается самым важным уровнем в контексте сокращения объема данных, передаваемых с сервера в браузер. В итоге ваш сайт может стать более отзывчивым, поскольку статичные ресурсы (CSS, JS, изображения) выводятся гораздо быстрее, если они кэшируются браузером.
Чтобы понять, как работает браузерный кэш, достаточно открыть вкладку Network в инструментах разработчика браузера. Давайте посмотрим, как кэш будет функционировать вживую. При загрузке первой страницы никаких ресурсов в кэше не появится.
Интересующие нас показатели – это объем переданных данных и общие ресурсы.
В итоге вы можете видеть, какой тип ресурсов занимает большую часть пропускной полосы.
Объем переданных данных будет всегда меньше, чем общий объем ресурсов, даже если это первая загрузка страницы браузером. На то есть несколько причин:
- Ресурсы, кэшированные браузером, никуда не пересылаются.
- Ресурсы, такие как HTML, CSS и JS, должны быть сжаты (Gzip) сервером перед отправкой в браузер. Затем они уже распаковываются браузером перед отображением для пользователей.
Следовательно, если кэширование настроено правильно, то в таком случае при последующих загрузках страницы должно передаваться меньше данных. Вы можете убедиться в этом сами, просто перезагрузив страницу.
Объем передаваемых данных упал с 1.2 Мб до 118 Кб, что является существенной экономией! Вы также можете видеть, что показатель нагрузки снизился с 893 мс до 573 мс.
Вы можете настроить поведение браузерного кэширования с помощью заголовков cache-control и expires, которые добавляются к ответу вашего сервера (при запросе статичных ресурсов). Заголовок cache-control будет иметь приоритет над более старым expires. Но применяются обычно оба заголовка для обеспечения совместимости с некоторыми устаревшими прокси-сервисами.
Вы можете проверить заголовки ресурсов с помощью инструментов разработчика или команды cURL:
$ curl -I https://spinupwp.com/wp-content/themes/spinupwp/assets/images/video-screenshot.png HTTP/2 200 server: nginx date: Mon, 18 Jan 2021 21:10:09 GMT content-type: image/png content-length: 46753 last-modified: Tue, 13 Oct 2020 12:58:40 GMT etag: "5f85a480-b6a1" expires: Tue, 18 Jan 2022 21:10:09 GMT cache-control: max-age=31536000
Заголовок cache-control обычно имеет значение max-age=<seconds> , что дает браузеру установку кэшировать файл на срок, не превышающий seconds. В итоге вы предотвратите повторную загрузку ресурса при последующих запросах. В приведенном выше случае файл будет кэширован браузером на срок до 1 года.
Распространенные проблемы с браузерным кэшированием
Инвалидация (аннулирование) кэша усложняется. Как только браузер кэшировал ресурс с помощью cache-control: max-age=<seconds>, вы уже не можете попросить браузер убрать его из кэша – по крайней мере, без изменения URL. Вот почему WordPress добавляет строку запроса версии к запрашиваемым ресурсам. Пример:
https://spinupwp.com/wp/wp-includes/css/dashicons.min.css?ver=5.2.2
Инструменты проверки скорости сайта, такие как Pingdom, будут жаловаться на недолговечные заголовки срока действия. Часто эти предупреждения появляются из-за сторонних ресурсов, таких как Google Analytics. Связано это с тем, что внешние сервисы стремятся гарантировать актуальность своих ресурсов вследствие уже упомянутых проблем с инвалидацией кэша.
Cache-control и expires – далеко не единственные заголовки, используемые браузером с целью понимания того, нужно ли получать ресурс с сервера. К примеру, по истечении времени, указанного в cache-control: max-age=<seconds>, будет использоваться заголовок etag. Он содержит валидационный токен (по аналогии с кэшем MD5 запрашиваемого ресурса), который сравнивается с токеном ресурса, хранящегося на сервере. Если значение etag совпадает, то в таком случае ресурс возвращает ответ «304 Not Modified». Браузер понимает, что кэшированный ресурс не изменился, а потому для него следует продлить срок действия, заданный в cache-control: max-age=<seconds>.
Страничное кэширование
Страничное кэширование дает лучший результат в контексте времени отклика приложения и пропускной способности. Страничный кэш превращает WordPress (CMS с базой данных) в статичный HTML-сайт, исключая PHP и MySQL из обработки запросов.
Чтобы продемонстрировать мощь страничного кэширования, я прибегну к чистой установке WordPress 5.6.2. Все тесты будут проводиться с помощью ApacheBench. В этих тестах я воспользуюсь стеком в виде SpinupWP с 8 GB, 4 vCPU DigitalOcean-дроплетом, заточенным под WP. Некэшированные результаты – это WordPress без кэширования (кроме PHP OPcache, использующего значения по умолчанию для PHP 7.4). Кэшированные результаты – это WordPress со страничным кэшированием, включенным в SpinupWP.
Начнем с количества запросов в секунду (чем больше, тем лучше, поскольку от этого зависит пропускная способность).
Здесь мы имеем 10-кратный прирост пропускной способности. Однако если эти запросы будут выполняться медленно, то в таком случае наша метрика потеряет всякую суть. По этой причине важно также измерить среднее время отклика (чем меньше, тем лучше):
Показатель среднего времени отклика в 5 раз лучше с включенным страничным кэшированием.
Распространенные проблемы со страничным кэшированием
Страничное кэширование чрезвычайно сложно настроить, когда на сайтах выводится персонализированный контент. К примеру, это интернет-магазины, форумы и т.д. Зачастую для таких ресурсов либо полностью отключается страничный кэш, либо задаются правила для исключения некоторых страниц из кэша (к примеру, страницы /checkout).
Инвалидация кэша может стать довольно заковыристой задачей. Из-за динамической природы WordPress довольно сложно определить, какие страницы следует удалять из кэша при обновлении контента (особенно если задействованы архивы, пагинация и виджеты). Вот почему очистка всего страничного кэша зачастую является предпочтительным подходом при изменении контента.
Использование нескольких решений для кэширования страниц только ухудшает производительность. Этот подход не рекомендован, поскольку может вести к инкогерентности кэша (в разных кэшах хранятся разные версии вашего сайта), что существенно усложнит его очистку.
Страничное кэширование обычно отключается для залогиненных пользователей (потому предпочтительным является объектное кэширование, которое мы рассмотрим далее).
Объектное кэширование
Как было отмечено выше, не все страницы можно кэшировать. Это особенно верно в отношении интернет-магазинов, сайтов сообществ и т.д., где нередко выводится персонализированный контент. То же самое и с админкой WordPress. Если бы такие динамические страницы были кэшированы, то пользователи увидели бы нерелевантный персонализированный контент.
В WordPress используется встроенное объектное кэширование, которое позволяет хранить в памяти такие данные, как запросы к БД. По этой причине несколько вызовов, скажем, get_posts приводят только к одному запросу к БД. Однако объектный кэш по умолчанию не является постоянным (персистентным). Он не живет после запроса. К счастью, WP можно интегрировать с постоянным хранилищем Redis, что имеет решающее значение для масштабирования динамических страниц. Объектный кэш расположен между PHP и базой данных, что ускоряет выполнение PHP и сокращает нагрузку на БД за счет кэширования запросов в памяти. Вы можете увидеть влияние объектного кэша, установив плагин Query Monitor. Загрузка страницы корзины WooCommerce без объектного кэширования дает 32 запроса к БД:
При включенном объектном кэшировании кол-во запросов к БД для этой страницы сокращается до 2, а время генерации страницы снижается с 0,085 с до 0,053 с.
Эти тесты были выполнены с использованием PHP 7.3, чистой установки WordPress 5.2.2, WooCommerce 3.6.4 и темы Storefront.
Распространенные проблемы
Чтобы сделать объектный кэш постоянным, требуется дополнительный серверный софт, такой как Redis или Memcached. Вы можете установить его самостоятельно, если у вас свой сервер.
Объектный кэш не позволяет избавиться от базы данных, которая является самым узким местом в WP. Связано это с тем, что SQL-запросы для построения индекса записей будут выполняться всегда, поскольку результаты не кэшируются.
Плагины кэширования в WordPress
Популярные плагины кэширования в WordPress — WP Rocket, W3 Total Cache или WP Super Cache, — являются распространенным способом добавления кэширования на сайт. Однако плагины нужны не всегда. Хорошие хостинг-провайдеры предлагают решения для кэширования на уровне сервера. Правда, в таком случае у вас должен быть доступ к серверу.
Источник: spinupwp.com