После деплоя пользователь видит старый CSS: как настроить версии ассетов

После деплоя разработчик видит новую верстку, а пользователь продолжает видеть старый CSS. В админке всё обновили, файлы на сервере свежие, но у части людей кнопки съехали, стили не применились или JavaScript ждёт другой HTML. Чаще всего причина в кэше браузера, CDN или серверных заголовках.

Проблема решается не просьбой “обновите страницу с Ctrl+F5”, а нормальной версионизацией ассетов.

Почему браузер берёт старый файл

Если CSS подключается одним и тем же URL, браузер имеет право использовать кэшированную копию.

<link rel="stylesheet" href="/css/app.css">

Если на сервере файл изменился, но URL тот же, пользователь может какое-то время видеть старый app.css. Особенно если настроен долгий Cache-Control.

Версия в query string

Простой способ — добавить версию в URL.

<link rel="stylesheet" href="/css/app.css?v=20260618">

После изменения версии браузер воспринимает это как новый ресурс. Такой вариант прост и подходит для многих небольших проектов.

Hash в имени файла

Более надёжный подход — включать hash содержимого в имя файла.

/assets/app.8f3a21.css
/assets/app.8f3a21.js

Когда файл меняется, меняется hash и URL. Старый файл может спокойно кэшироваться долго, потому что новый релиз подключает новый URL.

Cache-Control

Для файлов с hash можно ставить долгий кэш.

location ~* \.(css|js|png|jpg|jpeg|webp|svg|woff2)$ {
    expires 30d;
    add_header Cache-Control "public";
}

Для файлов без версии слишком долгий кэш опасен. Пользователь может долго получать старый CSS.

CDN

Если перед сайтом стоит CDN, обновление файла на сервере ещё не означает обновление у пользователя. Нужно проверить кэш CDN и правила purge.

  • есть ли CDN перед доменом;
  • кэширует ли он CSS и JS;
  • как очищается кэш после релиза;
  • учитывает ли CDN query string;
  • не отдаёт ли CDN старую версию по edge cache.

Порядок деплоя

Если HTML уже подключает новый файл, а сам файл ещё не загружен, пользователи получат 404 на CSS. Если файл заменили, а HTML ещё старый, будет обратная проблема. Поэтому порядок деплоя важен.

При hash-файлах обычно сначала загружают новые ассеты, потом переключают HTML или релизный symlink.

Смешивание старого JS и нового HTML

Особенно неприятная ситуация — HTML обновился, а JS остался старым. Тогда скрипт ищет старые селекторы или отправляет старый формат AJAX. Поэтому версионировать нужно не только CSS, но и JS.

<script src="/js/app.js?v=20260618"></script>

Как проверить

В браузере нужно открыть Network и посмотреть фактический URL CSS, HTTP-код, размер, заголовки Cache-Control и Age, если есть CDN.

curl -I https://example.ru/css/app.css

Если в заголовках стоит долгий max-age, а URL не меняется между релизами, проблема закономерна.

Чек-лист

  1. Проверить фактический URL CSS и JS в HTML.
  2. Проверить Cache-Control и expires.
  3. Добавить version query или hash в имя файла.
  4. Версионировать CSS и JS вместе.
  5. Проверить CDN и правила purge.
  6. Не ставить долгий кэш на неверсионированные файлы.
  7. Проверить порядок деплоя ассетов и HTML.
  8. После релиза проверить страницу в обычном браузере, не только с отключенным кэшем.

Кэш ассетов должен быть предсказуемым. Пользователь не обязан знать, как сбросить кэш браузера. Если URL файла меняется при изменении содержимого, старый CSS после деплоя перестаёт быть случайной проблемой.

Комментарии (0)

Пока нет комментариев. Будьте первым!