...

Кэширование WordPress и браузера - часто настроено неправильно

Кэширование в браузере WordPress часто приводит к медленным ответам, потому что операторам приходится Заголовок кэша настроены неправильно или вообще не контролируются. Я покажу вам, как типичные неправильные конфигурации возвращают 200 вместо 304, почему TTL отсутствуют и как правильно настроить кэширование в WordPress. Производительность отделка.

Центральные пункты

  • Длинный TTL для статических активов предотвращает ненужные запросы.
  • Четкое разделение статических и динамических путей защищает администратора и логин.
  • Одна система не смешивайте конкурирующие плагины для кэширования.
  • Проверьте заголовки с DevTools и статусом 304.
  • Кэширование на сервере и кэш браузера.

Как на самом деле работает кэширование браузера в WordPress

Браузер хранит статические файлы локально, что избавляет от необходимости их перезагрузки. HTTP-запросы. При втором посещении он считывает изображения, CSS и JS из локальной памяти и запрашивает изменения только у сервера. Это уменьшает объем данных, время отклика сокращается, а прокрутка сразу становится более отзывчивой. жидкость на. Если нет четких инструкций, браузер каждый раз полностью перезагружается, и время интерактивного взаимодействия страдает. Правильно установленные заголовки управления кэшем обеспечивают проверку 304, уменьшают пропускную способность и снижают нагрузку на PHP и базу данных. Я постоянно использую этот метод, потому что постоянное кэширование приносит наибольшую пользу повторяющимся пользователям.

Почему конфигурация часто не работает

Многие сайты предоставляют статические файлы с нелепо короткими max-age-значения. Некоторые плагины перезаписывают .htaccess друг друга и устанавливают противоречивые директивы. На сайте часто неправильно обозначаются пути к админке, из-за чего содержимое /wp-admin или /wp-login.php непреднамеренно попадает в кэш, а сессии сталкиваются. Я также проверяю разницу между первым и повторным вызовом, потому что это наглядно объясняет реальный опыт пользователей; сравнение подходит к следующему Первый звонок по сравнению с повторным звонком. Если вы все еще используете строки запросов без версионности, вы будете создавать старые файлы в памяти и удивляться тому, что устаревшие Стили.

Установите правильные заголовки кэша WP

Я контролирую продолжительность с помощью Управление кэшем и Expires, а также избегаю двусмысленных ETags в многосерверных средах. Для Apache я устанавливаю Expires на значимые значения и определяю „public, max-age“ для активов. Для Nginx я добавляю директивы add_header и слежу за тем, чтобы HTML хранился короткое время или „no-store“, если контент персонализирован. Я также деактивирую заголовки ETag, если балансировщики нагрузки или прокси-серверы не генерируют эти значения последовательно. Таким образом, я обеспечиваю четкое поведение браузера и избегаю Переоформление с каждым щелчком мыши.

ExpiresActive On
  ExpiresByType image/jpeg "доступ плюс 1 год"
  ExpiresByType image/png "доступ плюс 1 год"
  ExpiresByType text/css "доступ плюс 1 месяц"
  ExpiresByType application/javascript "доступ плюс 1 месяц"


<IfModule mod_headers.c
  Набор заголовков Cache-Control "public, max-age=31536000" "expr=%{CONTENT_TYPE} =~ m#^(image/|font/|application/javascript)#"
  Заголовок установлен Cache-Control "no-cache, no-store, must-revalidate" "expr=%{REQUEST_URI} =~ m#(wp-admin|wp-login.php)#"
  Заголовок без ETag
# Nginx
расположение ~* .(jpg|jpeg|png|gif|ico|webp|avif|css|js|woff2?)$ {
    add_header Cache-Control "public, max-age=31536000";
}
location ~* /(wp-admin|wp-login.php)$ {
    add_header Cache-Control "no-store";
}

Расширенные директивы управления кэш-памятью в повседневной жизни

Помимо „max-age“ и „no-store“, современные директивы обеспечивают заметную стабильность. „immutable“ сигнализирует браузеру, что файл не изменится, пока его имя остается неизменным - идеальный вариант для версионных активов. „stale-while-revalidate“ позволяет доставлять просроченную копию, пока она обновляется в фоновом режиме. „stale-if-error“ сохраняет копию готовой, если Origin ненадолго возвращает ошибки. „s-maxage“ предназначен для прокси/CDN и может иметь значения, отличные от „max-age“. Также важно: „public“ позволяет кэшировать на общих прокси-серверах; „private“ ограничивается браузером. „no-cache“ означает не „не кэшировать“, а „кэширование разрешено, но перепроверяйте перед использованием“ - принципиальное отличие от „no-store“.

Пример # Apache 2.4 (еще более надежное кэширование активов)

  Набор заголовков Cache-Control "public, max-age=31536000, immutable, stale-while-revalidate=86400, stale-if-error=259200" "expr=%{REQUEST_URI} =~ m#.(css|js|woff2?|png|jpe?g|webp|avif)$#"
  Набор заголовков Cache-Control "no-cache, must-revalidate" "expr=%{CONTENT_TYPE} =~ m#^text/html#"
# Пример Nginx (304/Include редиректы)
location ~* .(css|js|woff2?|png|jpe?g|webp|avif)$ {
    add_header Cache-Control "public, max-age=31536000, immutable, stale-while-revalidate=86400, stale-if-error=259200" always;
}
location ~* .html$ {
    add_header Cache-Control "no-cache, must-revalidate" всегда;
}

Рекомендуемая продолжительность кэширования по типам файлов

Я выбираю время в зависимости от частоты изменений, а не от привычки, потому что Активы стареют по-разному. Изображения, логотипы и иконки обычно остаются актуальными в течение длительного времени, в то время как CSS/JS подвергаются более частым итерациям. Веб-шрифты редко меняются, но требуют постоянных CORS-заголовков. HTML часто служит контейнером для динамического контента и поэтому может быть недолговечным или только перепроверяться. API должны иметь четко определенные правила, чтобы клиенты могли корректно работать с JSON избегать.

Тип файла Рекомендация Cache-Control Подсказка
Изображения (jpg/png/webp/avif/svg) общедоступно, max-age=31536000 Использование годового кэша с версионированием файлов
CSS/JS общедоступно, max-age=2592000 Добавление версии к имени файла для обновлений
Шрифты (woff/woff2) общедоступно, max-age=31536000 Установите правильную настройку Access-Control-Allow-Origin
HTML (страницы) no-cache, must-revalidate или short max-age Очень осторожно с динамическим контентом
REST API (json) частный, max-age=0, must-revalidate Дифференцировать по конечным точкам

Избегайте конфликтов с плагинами

Я использую не более Плагин кэширования и проверьте, не прописаны ли в хостинге правила на уровне сервера. Такие комбинации, как W3 Total Cache плюс WP Super Cache, часто создают дублирующие директивы, которые отменяют друг друга. WP Rocket предлагает быструю настройку, но требует четких исключений для динамических путей и электронной коммерции. В любом случае я проверяю созданный .htaccess после сохранения, чтобы выявить нелогичные заголовки. Затем я проверяю критические страницы, такие как оформление заказа, вход в систему и персонализированные приборные панели, на правильность Обход.

Кэширование и куки: зарегистрированные пользователи, WooCommerce, сессии

HTML для вошедших в систему пользователей не должен храниться в общедоступном кэше. WordPress устанавливает такие файлы cookie, как wordpress_logged_in_, WooCommerce дополнен woocommerce_items_in_cart, wp_woocommerce_session_ и другие. Вместо Передача: Cookie Я полностью обхожу кэш для таких запросов. Это обеспечивает стабильность процесса оформления заказа и корректность персонализированных областей. Я также использую правила на стороне сервера, которые устанавливают более строгие заголовки при распознавании файлов cookie.

# Apache: распознавание файлов cookie и установка обходных заголовков

  SetEnvIfNoCase Cookie "wordpress_logged_in_|woocommerce_items_in_cart|wp_woocommerce_session" has_session
  Установите в заголовке Cache-Control "private, no-store" env=has_session
# Nginx: обход на основе куки
if ($http_cookie ~* "(wordpress_logged_in|woocommerce_items_in_cart|wp_woocommerce_session)") {
    add_header Cache-Control "private, no-store" always;
}

Многие плагины кэширования предлагают флажки для этого (WooCommerce/Cart/Exclude checkout). Важно: Nonces (_wpnonce) в формах и Heartbeat API часто меняются. Я слежу за тем, чтобы HTML на фронтэнде с нонсами не кэшировался постоянно или работал через „no-cache, must-revalidate“.

Целевое лечение HTML: персонализированное и общее

Не все страницы одинаковы. Статьи, целевые страницы и юридические страницы часто можно кэшировать с коротким TTL или повторной проверкой. Архивы, страницы поиска, приборные панели, области учетных записей и оформления заказа остаются динамичными. Если речь идет о кэшировании страниц, я придерживаюсь следующей практики: кэшируйте только публичный HTML без куки, в противном случае - „приватный“ или „no-store“. Если вы тестируете микрокеширование (например, 30-60 секунд для высокочастотных, неперсонализированных страниц), вам следует определить строгие исключения для параметров запроса и сессий. В WordPress есть DONOTCACHEPAGE константа, которую шаблоны могут устанавливать на сложных страницах - я использую ее постоянно, чтобы избежать ошибок.

Разумно сочетайте кэширование на стороне сервера

Кэширование браузера заканчивается на клиенте, но я также освобождаю сервер от кэша страниц, объектов и опкодов для реальной Пики нагрузки. Кэширование страниц обеспечивает статический HTML еще до запуска PHP. Redis или Memcached уменьшают количество запросов к базе данных при повторных запросах и заметно сокращают TTFB. OPcache предоставляет прекомпилированные фрагменты байткода PHP и тем самым сокращает время выполнения. В конце концов, главное - это чистая связь между кэшем сервера и кэшем браузера, чтобы второе посещение было более или менее успешным. мгновенно работает.

Интеграция с CDN без сюрпризов

CDN используют собственную логику TTL и реагируют на „s-maxage“. Поэтому я делаю четкое различие: „max-age“ для браузеров, „s-maxage“ для Edge. Если развертывание еще не завершено, я запускаю целевую очистку вместо глобального уничтожения „Cache Everything“. Важно: Кэшируйте HTML в Edge только в том случае, если не используются файлы cookie. В противном случае создаются некорректные состояния, поскольку кэш edge разделяет персонализированные ответы. Для активов я устанавливаю длительные TTL и полагаюсь на версионирование имен файлов. CDN могут игнорировать строки запроса - еще одна причина хранить версии в имени файла. Нормализация заголовков (отсутствие лишних значений „Vary“, согласованность „Content-Type“) предотвращает раздувание ключей кэша.

Шаг за шагом: чистая установка

Я начинаю с плагина и активирую кэширование браузера для CSS, JS, изображений и шрифтов, прежде чем активировать хтакесс завершить. Затем я устанавливаю высокий max-age для статических активов и предоставляю HTML с коротким временем или правилами no-cache. Я отключаю ETags, если задействовано несколько серверов, и полагаюсь на Last-Modified плюс 304. Затем я запускаю предварительную загрузку, чтобы важные страницы были сразу доступны в виде статических копий. Наконец, я проверяю пути к магазину, логину и администратору, чтобы не допустить сохранения приватного содержимого в буферная память земля.

Практическая диагностика с помощью CLI и проверки заголовков

DevTools обязательны, но я углубляюсь в CLI-тесты. A завиток -I показывает заголовок без загрузки; с -H Я моделирую условия. Например, я проверяю, действительно ли повторные проверки возвращают 304, увеличивается ли „Возраст“ от прокси/CDN и отключают ли cookies кэширование.

# Показать заголовок
curl -I https://example.com/style.css

Имитация повторной проверки # (If-Modified-Since)
curl -I -H "If-Modified-Since: Tue, 10 Jan 2023 10:00:00 GMT" https://example.com/style.css

Проверка # с помощью cookie (должен быть принудительный обход)
curl -I -H "Cookie: wordpress_logged_in_=1" https://example.com/

Я слежу за тем, чтобы у активов было длинное значение „контроль кэша“, в идеале - „неизменяемый“. HTML должен иметь значение „no-cache“ или короткий TTL. Если я все еще получаю 200 вместо 304, часто в игре есть редиректы, которые аннулируют ETags/Last-Modified. Кроме того, „add_header“ в Nginx по умолчанию применяется только к ответам 200 - с „always“ я также устанавливаю заголовки для 304 и 301/302.

Тестирование и проверка заголовков

Я открываю DevTools, перезагружаю страницу один раз, очищаю кэш и перезагружаю, чтобы получить 304 против 304. 200 чтобы наблюдать. В сетевой панели я проверяю контроль кэша, возраст, ETag/load-modified и размер ответа. Если вместо повторных проверок все еще есть прямые попадания, я проверяю конфликты с перенаправлениями, куками или строками запросов. В сложных случаях мне помогает эта статья о подводных камнях с заголовками: Саботаж заголовка кэша. Я повторяю проверку после каждого обновления плагина, потому что изменения в правилах часто вносятся молча. пройти.

Версионирование, CDN и кэширование

Я вешаю Версия в именах файлов (style.23.css вместо style.css?ver=23), чтобы браузеры сохраняли длинные кэши и при этом сразу загружали новый контент. CDN распространяет статические файлы глобально, устанавливает собственные TTL в пограничных точках и значительно сокращает RTT. Важно: кэшируйте HTML в CDN только в том случае, если не требуется персонализация, иначе будут созданы неверные состояния. Во время развертывания я автоматически меняю номер версии, чтобы пользователи не застряли со старыми скриптами. Вот как я сочетаю жесткие TTL браузера с безопасностью Очистка кэша.

Чистая версионность в сборках WordPress

Наиболее надежным является конвейер сборки, который записывает хэши в имена файлов (например. app.9f3c.css). Затем WordPress загружает именно этот файл - браузеры могут хранить его в течение года благодаря „immutable“. В качестве запасного варианта, если имена файлов не могут быть изменены, я устанавливаю номер версии динамически, исходя из даты файла. Это позволяет сохранить корректность и надежность строк запросов.

// functions.php (обратная версификация через filemtime)
add_action('wp_enqueue_scripts', function () {
    $css = get_stylesheet_directory() . '/dist/style.css';
    $ver = file_exists($css) ? filemtime($css) : null;
    wp_enqueue_style('theme', get_stylesheet_directory_uri() . '/dist/style.css', [], $ver);
});

Важно: Если имя файла содержит версии, может быть установлено значение „immutable“. Если вы используете только строки запросов, браузеры должны иметь возможность перепроверки, чтобы обновления поступали надежно. Я также слежу за тем, чтобы инструменты сборки очищали старые файлы, чтобы CDN не хранили неоправданно большое количество вариантов.

Кэширование и правильная загрузка веб-шрифтов

Веб-шрифты нуждаются в длинных TTL, правильных CORS-заголовках и необязательной предварительной загрузке, чтобы Прыжки с макетом не появляются. Я размещаю файлы woff2 на том же домене или устанавливаю Access-Control-Allow-Origin в чистом виде. Кроме того, определите font-display: swap, чтобы текст оставался видимым сразу же, пока шрифт загружается. Если вы хотите оптимизировать время загрузки ваших шрифтов, вы найдете полезные советы здесь: Ускоренная загрузка веб-шрифтов. Благодаря чистым заголовкам кэша и предварительному подключению к CDN я заметно сокращаю время FOUT/FOIT и обеспечиваю последовательность Рендеринг-Результаты.

Правильная настройка шрифтов, CORS и Vary

Шрифты из другого Origin требуют CORS. Я установил Access-Control-Allow-Origin (например, в свой собственный домен или „*“ для действительно публичных) и избежать ненужных Переменная: Происхождение, который раздувает ключи кэша. Рекомендуется для шрифтов: public, max-age=31536000, immutable. Предварительная загрузка улучшает First Paint, но не изменяет TTL - предварительная загрузка и жесткое кэширование дополняют друг друга. Я также не забываю, что сжатая доставка (br/gzip) a Vary: Accept-Encoding требуется для корректного разделения прокси-серверов.

Типичные ошибки и быстрые решения

Если после обновления появляется старый код, то Версионирование на имени файла. Если браузер каждый раз полностью перезагружается, в заголовках заданы противоречивые инструкции или прокси удаляют их по пути. Если оформление заказа отменяется, вероятно, сайт кэширует страницы на стороне сессии или ответы API. Если пути к админке попадают в кэш, значит, отсутствуют исключения для wp-admin и login или плагин кэширует глобально. Я решаю эту проблему путем пошаговой деактивации, объединения заголовков, исключения критических путей и, наконец, эффекта со статусом 304. подтвердить.

Часто упускаемые из виду детали, которые имеют большое значение

  • Nginx add_header не применяется к 304/redirects без „always“ - заголовки кэша в этом случае не проходят валидацию. Я постоянно устанавливаю „всегда“.
  • Expires против управления кэшем: „Cache-Control“ имеет приоритет, „Expires“ служит запасным вариантом для старых клиентов. Избегайте дублирования и противоречивой информации.
  • ETag в многосерверных системах: Несогласованные ETags уничтожают 304. Я отключаю ETags или использую слабые валидаторы и полагаюсь на „Last-Modified“.
  • Варьируйте до минимума: „Vary: Accept-Encoding“ обязателен для сжатия, „Vary: Cookie“ раздувает краевые кэши - лучше обходить стороной cookie-based.
  • SVG и тип MIME: Правильно image/svg+xml установить, дать длительный TTL и рассмотреть возможность использования встроенных SVG для критических иконок.
  • Избегайте цепочек перенаправления: Каждый 301/302 может потерять валидаторы и заставить 200 - чистые URL без каскадов.
  • Целенаправленно используйте приоритет/предварительную нагрузку: fetchpriority="high" Предварительная загрузка критически важных объектов ускоряет первое обращение; кэширование эффективно для возвращающихся пользователей.
  • Различайте REST-API: Публичные, редко меняющиеся JSON можно кэшировать на короткое время; конечные точки с токенами/куки строго „приватны“.

Краткое резюме

Я полагаюсь на четкое Правиладлинные TTL для активов, короткие или перепроверяемые HTML-ответы, версионирование и один плагин кэширования. Затем я объединяю кэш браузера с кэшем страниц, объектов и опкодов, чтобы снизить нагрузку на сервер. Я проверяю DevTools, ищу 304, проверяю заголовки и устраняю конфликты с перенаправлениями или cookies. Для практической проверки я сравниваю результаты измерений при первом и повторном обращении и фокусируюсь на заметных улучшениях. Если вы будете следовать этим шагам, то сможете вывести WordPress на надежный уровень браузерного кэширования. Скорость и радует пользователей и поисковые системы.

Текущие статьи