Как обновлять JavaScript и CSS без старого кеша: версии файлов и безопасный выпуск
Cache busting означает смену URL изменившегося JavaScript или CSS, часто с хешем содержимого в имени файла. Такие версии можно кешировать надолго, а HTML должен достаточно быстро узнавать о новом выпуске через короткий срок свежести или повторную проверку.
В этом руководстве
- Разделите HTML и ресурсы с версиями
- Назначьте заголовки в соответствии со схемой выпуска
- Версия в параметре запроса зависит от ключа кеша
- Найдите слой, который продолжает отдавать старые байты
- Сохраните совместимость старых страниц и возможность отката
- После исправления оцените повторное использование
- Частые вопросы
- Источники и определения
Если новый выпуск выглядит правильно в приватном окне, а постоянный посетитель видит старый интерфейс, сначала сравните адреса ресурсов. Публикация могла заменить файл на сервере, но в браузере всё ещё остаётся свежий кешированный ответ по прежнему URL.
Надёжная схема явно связывает HTML с определённой версией файлов. В примере одновременно доступны старый и новый наборы: страница, открытая до публикации, продолжает получать совместимые ресурсы.
Разделите HTML и ресурсы с версиями
Думайте об HTML как о небольшом манифесте выпуска. Версия A ссылается на app.4c21.js и site.19ab.css. Версия B меняет приложение и указывает app.9d80.js. Если байты CSS не изменились, ссылка site.19ab.css сохраняется. Имена хешей здесь условные: это не вычисленные контрольные суммы настоящих файлов.
Неизменившиеся ресурсы используются повторно, а изменившиеся получают отдельный адрес в кеше. Поэтому слишком долгий срок свежести HTML способен задержать обновление: получая прежний документ, посетитель продолжает запрашивать прежние версии файлов.
| Ресурс | Выпуск A | Выпуск B | Ожидаемое поведение |
|---|---|---|---|
| Документ HTML | Ссылается на app.4c21.js | Ссылается на app.9d80.js | Повторная проверка или намеренно короткий срок свежести |
| JavaScript приложения | app.4c21.js | app.9d80.js | Новый URL при изменении байтов |
| Неизменившийся CSS | site.19ab.css | site.19ab.css | Повторное использование того же URL |
| Предыдущие ресурсы | Доступны | Остаются доступны старым страницам | Сохраняются на необходимый срок совместимости |
Назначьте заголовки в соответствии со схемой выпуска
Для публичного файла, содержимое которого никогда не меняется по данному URL, уместны долгий max-age и immutable. Для HTML директива no-cache разрешает хранение, но требует проверки перед повторным использованием. Это отличается от no-store, который просит не сохранять ответ. Политику нужно выбирать по ресурсу, а не копировать одинаковый заголовок на весь сайт.
Приведённые заголовки показывают подход, а не универсальную настройку. Проверьте, что действительно отдаёт ваш хостинг и как устроен кеш CDN. Наличие строки в локальном конфигурационном файле ещё не доказывает, что ту же политику получили публичный браузер и пограничный узел.
Versioned public asset: /assets/app.9d80.js
Cache-Control: public, max-age=31536000, immutable
HTML document: /index.html
Cache-Control: no-cache
The URL /assets/app.9d80.js must continue to serve the same bytes.Версия в параметре запроса зависит от ключа кеша
Адрес /app.js?v=release-b может отличаться для кеша от /app.js?v=release-a. Однако каждый соответствующий слой должен учитывать этот параметр в ключе кеширования. Если правило CDN игнорирует строку запроса, оба адреса могут обращаться к одному сохранённому объекту, и ожидаемого разделения версий не получится.
Случайное значение при каждой загрузке страницы уничтожает полезное повторное использование. Лучше стабильный хеш содержимого или номер выпуска, меняющийся вместе с ресурсом. Фрагмент вида /app.js#release-b для этой цели не подходит: часть после решётки не передаётся в HTTP-запросе.
Найдите слой, который продолжает отдавать старые байты
Сопоставьте HTML-ответ, указанный в нём URL ресурса и сам ответ по этому адресу у затронутого посетителя. Если документ ссылается на старый хеш, проверяйте свежесть HTML. Если хеш новый, а содержимое старое, исследуйте публикацию, ключ кеша и ответ исходного сервера. При правильных сетевых ответах проверьте уже работающую страницу и service worker.
Очистка CDN не удаляет свежий ответ, уже лежащий в каждом браузере. Принудительная перезагрузка браузера, наоборот, помогает только локальной диагностике и не исправляет выпуск для всех. Записывайте, какой слой обошли при каждой проверке: тогда успешный результат можно воспроизвести.
- Сохраните конечный URL HTML и адрес подключаемого скрипта или таблицы стилей.
- Проверьте статус, Content-Type, Cache-Control, ETag и доступные заголовки состояния кеша.
- Убедитесь, что версия возвращает нужные байты, а не резервную HTML-страницу.
- Если установлен service worker, отдельно изучите правила его кеша.
- Проверьте и чистое посещение, и страницу, оставленную открытой на время выпуска.
Сохраните совместимость старых страниц и возможность отката
Загрузите новые ресурсы до публикации ссылающегося на них HTML либо используйте платформу, переключающую выпуск целиком. Предыдущие файлы должны оставаться доступными достаточно долго для старых документов и открытых вкладок. Дополнительный модуль может понадобиться странице значительно позже первоначального открытия.
Например, выпустите B при наличии файлов A и B, проверьте новый интерфейс и сохраните возможность вернуть HTML на A. Немедленное удаление app.4c21.js способно сломать старый документ. Замена содержимого по тому же хешированному адресу тоже нарушает договор версий и делает откат непредсказуемым.
После исправления оцените повторное использование
Проверьте небольшую последовательность: первый визит загружает ресурсы, следующий повторно использует подходящие ответы, а новый выпуск получает только изменившиеся версии. Смотрите настоящую передачу данных, включая запросы повторной проверки. Разные ответы из кеша не обязательно имеют одинаковую сетевую стоимость.
Калькулятор экономии кеша оценивает снижение обращений к исходному серверу по заданной вами доле попаданий. Калькулятор передачи данных связывает число запросов с размером ответа. Оба полезны для сравнения явного плана, но не заменяют измерение публичных заголовков и настоящего поведения кеша.
Частые вопросы
Нужно ли полностью отключить кеш ради обновления CSS?
Сначала найдите устаревший документ или ресурс и настройте стабильные версии. Полное отключение повторного использования увеличивает передачу данных и задержки, но само по себе не объясняет ошибку процесса публикации.
Заменит ли новый ETag свежий файл в браузере немедленно?
Пока ответ свежий, браузер может использовать его без обращения к серверу. Новый URL содержимого позволяет не ждать будущей проверки старого ресурса.
Когда можно удалять прежние файлы с хешами?
После необходимого срока совместимости с кешированным HTML, открытыми вкладками и откатом. Сохраняйте файлы, пока на них может ссылаться поддерживаемый документ.
Источники и определения
Метод проверен: