Кэширование браузером через .htaccess: готовая конфигурация
Готовый блок mod_expires и mod_headers для статических ресурсов сайта на Apache. Cache-control на год для CSS, JS, шрифтов и картинок.
Содержание
- Зачем браузерный кеш
- Что кешировать и на сколько
- Готовая конфигурация .htaccess
- Что делает immutable
- Сжатие через mod_deflate
- Что НЕ кешировать
- Проверка работы кеша
- Особенности для WordPress
- Особенности для Битрикса
- Особенности для shared-хостинга
- Как обновлять файлы при кеше
- Что делать после установки
- Чек-лист правильной настройки
- Когда стоит делегировать
- Частые вопросы
Браузерный кэш ускоряет повторные заходы и снимает 200-500 мс с отрисовки. Настраивается одним блоком в .htaccess: год для картинок, шрифтов, CSS и JS с версионированием, 5-15 минут для HTML. Без версионирования в имени файла длинный кэш ставить нельзя.
Браузерный кеш это самый дешёвый способ ускорить сайт для повторных посетителей. Один правильный блок в .htaccess отдаёт на каждом ответе заголовок Cache-Control: max-age=31536000, и при следующем заходе браузер не идёт за CSS, JS, картинками на сервер. LCP опускается на 200-500 миллисекунд, нагрузка на хостинг падает в разы.
Но многие сайты в 2026 году по-прежнему отдают статику с заголовком Cache-Control: no-cache или max-age=0, и каждый посетитель скачивает всё заново. Разберу готовую рабочую конфигурацию для Apache shared-хостинга и что в ней важно.

Зачем браузерный кеш
Когда браузер загружает страницу, он скачивает HTML, CSS, JS, картинки, шрифты. Если все эти файлы пометить Cache-Control: max-age=31536000 (год), браузер сохраняет копию у себя.
При следующем посещении той же страницы: — HTML может качаться заново (он часто меняется). — CSS, JS, картинки, шрифты браузер берёт из кеша. Запросов к серверу нет.
Что это даёт: — Скорость первой и второй страницы. На повторных переходах LCP падает до 0.5-1 секунды. — Меньше нагрузки на хостинг (и меньше расходов на трафик). — Лучше для пользователя на медленной сети: повторное открытие моментально.
Кеш не помогает первому посещению. Тут работают другие оптимизации (CDN, сжатие, минификация). Браузерный кеш для постоянной аудитории.
Что кешировать и на сколько
Принцип: то, что меняется редко, кешируем надолго. То, что часто, недолго или не кешируем.
| Тип файла | Срок кеша | Комментарий |
|---|---|---|
| Шрифты (.woff2) | 1 год | Меняются почти никогда |
| Картинки (.jpg, .png, .webp, .avif, .svg) | 1 год | Если используете хеш в имени |
| CSS, JS | 1 год | При условии хеша в имени |
| Видео | 1 год | |
| Иконки favicon | 7-14 дней | Иногда меняется |
| HTML | 5-15 минут или без кеша | Часто обновляется |
| API-ответы | без кеша | Динамические данные |
Главное условие для долгого кеша: имя файла должно меняться при изменении содержимого. Если у вас style.css, и вы его правите, браузер всё равно будет показывать старый кеш. Решение это style.abc123.css, где abc123 меняется при каждой сборке.
Большинство современных сборщиков (Vite, Webpack, Astro, Next.js) делают это автоматически. На WordPress зависит от плагина: WP Rocket, Autoptimize и подобные ставят хеши в имена сжатых файлов.
Готовая конфигурация .htaccess
Базовая рабочая версия:
# Включаем модули
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 month"
# Картинки
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/avif "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 week"
# Шрифты
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType application/font-woff "access plus 1 year"
ExpiresByType application/font-woff2 "access plus 1 year"
# CSS и JS
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType text/javascript "access plus 1 year"
# Видео
ExpiresByType video/mp4 "access plus 1 year"
ExpiresByType video/webm "access plus 1 year"
# HTML и API: короткий кеш
ExpiresByType text/html "access plus 5 minutes"
ExpiresByType application/json "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
</IfModule>
# Заголовок Cache-Control с immutable для статики с хешем
<IfModule mod_headers.c>
<FilesMatch ".(jpg|jpeg|png|webp|avif|gif|svg|woff2|woff|css|js|mp4|webm)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# HTML без длинного кеша
<FilesMatch ".(html|htm)$">
Header set Cache-Control "public, max-age=300, must-revalidate"
</FilesMatch>
# API-ответы не кешируются
<FilesMatch ".(json|xml)$">
Header set Cache-Control "no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "0"
</FilesMatch>
</IfModule>
Кладёте в public_html/.htaccess. Через минуту, без перезапуска Apache, правила работают.
Что делает immutable
Заголовок Cache-Control: public, max-age=31536000, immutable это идеальная комбинация для статики с хешем в имени.
public означает кеш можно держать в любом промежуточном кеше (CDN, прокси).
max-age=31536000 это 1 год в секундах.
immutable говорит браузеру, что файл не меняется. Это значит, что даже при Reload (Ctrl+R) браузер не идёт за файлом проверять. Файл всегда из кеша.
Это безопасно ровно потому, что у файла хеш в имени. Если нужно поменять CSS, имя поменяется (style.def456.css), и страница укажет на новый файл.
immutable поддерживается всеми современными браузерами с 2018-го.
Сжатие через mod_deflate
Кеширование работает в паре со сжатием. Сжатый файл занимает меньше места, поэтому его быстрее качать первым посетителям.
Добавляем к .htaccess:
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom+xml
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE font/woff
AddOutputFilterByType DEFLATE font/woff2
</IfModule>
Это включает gzip-сжатие для текстовых форматов. На большинстве хостингов работает.
Brotli (более эффективное сжатие) поддерживается через mod_brotli, но он чаще доступен только на VPS. Если на shared только gzip, это нормально, разница 10-20 процентов в размере.
Что НЕ кешировать
Несколько важных исключений.
admin-страницы
Админка WordPress, Битрикса, любой CMS не должна попадать под долгий кеш. Иначе пользователи увидят кешированную версию, и при действиях возникают сбои.
Обычно это решается тем, что админка работает по другому пути (/wp-admin/) и отдаёт другой Cache-Control через PHP-заголовки. Дополнительная настройка в .htaccess не нужна.
Но проверьте, что ваш блок выше не накладывается на админку. В стандартном .htaccess для WordPress правила mod_rewrite для админки идут отдельно, и кеш на них не накладывается.
Корзина магазина и личный кабинет
/cart/, /checkout/, /my-account/ нельзя кешировать. Они должны отдавать private, no-cache.
Если у вас Apache, добавьте отдельное правило:
<IfModule mod_headers.c>
<FilesMatch "(cart|checkout|my-account)">
Header set Cache-Control "private, no-cache, must-revalidate"
</FilesMatch>
</IfModule>
Но это работает не идеально. Лучше, чтобы PHP-движок (WordPress, WooCommerce) сам ставил заголовок при ответе на эти страницы. WooCommerce из коробки делает это правильно.
Динамические JSON-ответы
API-ответы вашего сайта (REST API WordPress, Битрикс REST) не должны попадать под долгий кеш. Раздел в .htaccess для application/json обычно ставит no-cache, но проверяйте.

Проверка работы кеша
После публикации .htaccess проверяете, что заголовки реально отдаются.
Через curl
curl -sI https://saitfix.ru/style.css
Должны увидеть:
Cache-Control: public, max-age=31536000, immutable
Expires: ...
Content-Type: text/css
Если Cache-Control не виден, конфиг не применился. Проверяйте, что mod_headers и mod_expires включены на хостинге.
Через DevTools
Открываете сайт, F12 > Network. Перезагружаете. Смотрите на CSS и JS в списке. Колонка Status: — 200: первый раз скачивается. — 200 (from cache): из кеша браузера. — 304 Not Modified: проверка по If-None-Match.
После активации кеша при повторной загрузке вы увидите много from cache.
Также в колонке Size рядом со словом disk cache или memory cache будет указано, откуда взято.
Через Yandex Метрика и PageSpeed Insights
PageSpeed Insights в разделе Diagnostics показывает рекомендацию Serve static assets with an efficient cache policy. Если она не активна, значит у вас всё хорошо. Если активна, перечислены файлы, которые кешируются плохо.
Особенности для WordPress
WordPress сам по себе не управляет браузерным кешем для статики. Это делает либо ваш .htaccess, либо плагин кеширования.
Плагины, которые ставят правильные правила: — WP Rocket (платный). — W3 Total Cache (бесплатный, сложный). — WP Super Cache (бесплатный, простой). — Cache Enabler (бесплатный, минималистичный).
При использовании плагина проверяйте: правильные ли он добавляет правила, не дублируются ли с вашими ручными.
Если используете руками, плагин не нужен, или включаете только функцию объединения CSS/JS.
Особенности для Битрикса
Битрикс генерирует свои .htaccess правила для оптимизации. В стандартном файле есть блок mod_expires и mod_headers, но он часто базовый.
Можно дополнить или заменить своим. Главное: соблюдайте порядок правил в .htaccess. Битриксовые блоки идут раньше, ваши ниже.
Особенности для shared-хостинга
На некоторых shared-хостингах модули mod_expires и mod_headers отключены. Признак: правила в .htaccess пишете, но эффекта нет.
Проверка: phpinfo() или ответ хостинга. Если модули выключены, обращайтесь в поддержку с просьбой включить. Большинство российских хостингов идут навстречу.
Если хостинг наотрез отказывает (бывает на самых дешёвых тарифах), часть кеширования можно сделать через <meta http-equiv="cache-control" ...> в HTML, но это работает только для HTML, не для статики.
Как обновлять файлы при кеше
Главная сложность долгого кеша: пользователи видят старые версии CSS/JS до момента, пока кеш не истечёт (год).
Решение: hash в имени файла.
При сборке сайта вы получаете style.abc123.css. При следующей сборке после правки style.def456.css. HTML ссылается на актуальную версию. Старые версии остаются в кеше браузеров, но никто на них не ссылается, и они со временем сами очищаются.
Современные сборщики (Vite, Webpack, Astro):
<link rel="stylesheet" href="/_astro/index.abc123.css">
При каждой сборке хеш меняется, если содержимое изменилось.
Если вы делаете сайт без сборщика, простой способ это query-параметр с версией:
<link rel="stylesheet" href="/style.css?v=20260604">
Меняете дату при каждой правке. Браузер видит новую версию, идёт за ней. Не идеально (не работает с immutable), но рабочее.
Что делать после установки
После публикации .htaccess:
- Проверьте через curl, что заголовки приходят.
- Откройте сайт в новом окне (incognito), F12 > Network, посмотрите на каждом файле колонку
Cache-Control. Должны увидетьmax-age=31536000. - Перезагрузите страницу. Большинство файлов должны идти
from cache. - Прогоните PageSpeed Insights. Раздел
Serve static assets with an efficient cache policyдолжен исчезнуть из ошибок.
Через 2-4 недели в Яндекс Метрике должна стать заметно лучше скорость для возвращающихся пользователей. У случайных одноразовых эффект минимальный.

Чек-лист правильной настройки
- В
.htaccessесть блок mod_expires. - В
.htaccessесть блок mod_headers с Cache-Control. - Картинки, шрифты, CSS, JS получают
max-age=31536000, immutable. - HTML получает короткий кеш (5-15 минут).
- API и JSON не кешируются.
- Корзина и личный кабинет не кешируются.
- Имена статичных файлов содержат хеш или версию.
mod_deflateилиmod_brotliвключены для сжатия.- Проверка через curl показывает правильные заголовки.
- Проверка через DevTools показывает
from cacheна повторных загрузках. - PageSpeed не выдаёт жалоб на кеш.
Когда стоит делегировать
Постановка кеширующего блока на типичном сайте занимает 1-2 часа. На сайте с большим количеством исключений (магазин с динамическими страницами, личным кабинетом) до 4-6 часов с тестированием.
Эта работа входит в часовую ставку или в любой из тарифов на /#pricing. Если у вас сайт долго грузится при повторных посещениях, или PageSpeed жалуется на отсутствие кеша, опишите ситуацию через /#contact. Связанные материалы по скорости в /blog/category/speed/, там есть отдельные статьи про CDN, шрифты и lazy load.
Частые вопросы
Что даёт браузерный кэш
При повторном заходе браузер не идёт на сервер за картинками, стилями и скриптами, а берёт их с диска. Первая отрисовка ускоряется на сотни миллисекунд, нагрузка на хостинг падает.
Что и на сколько кэшировать
Картинки, шрифты, CSS и JS на год, если в имени файла или в адресе есть версия. Иконку сайта на неделю-другую. HTML на 5-15 минут или без кэша вовсе, он меняется чаще всего.
Что означает immutable
Обещание браузеру, что файл по этому адресу больше не изменится. Тогда он не будет даже переспрашивать сервер. Ставить можно только на файлы с версией в имени или в параметре.
Почему правки в стилях не видны
Потому что браузер держит старый файл из кэша. Лечится не сбросом кэша у каждого посетителя, а сменой версии в адресе файла: новый адрес значит новая загрузка.