Sanyanggae LogoSanyanggae

💻 Веб и фронтенд

Разница между no-cache и no-store в HTTP: проверяем обновления через ETag и 304

Разделяем хранение и повторную проверку, разбираем Cache-Control, ETag и ответы 304 на вымышленном расписании и сужаем поиск причины устаревшего экрана.

사냥개 (Sanyanggae)Опубликовано Обновлено 16 мин. чтения

Это перевод корейского оригинала. Корейский оригинал · Проверка перевода: Проверка с помощью ИИ

Поясняющая схема HTTP-кеша: хранение и повторное использование, проверка ETag, ответы 200 и 304.
Поясняющая схема Sanyanggae. Три карточки различают хранение и повторное использование, проверку ETag и ответы 200/304.

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

HTTP-кеш сохраняет полученные ответы и повторно использует их при подходящих условиях. В статье на вымышленном примере общедоступного расписания связываются указания Cache-Control о хранении и проверке с ETag и ответами 304. Приведённые обмены сокращены для объяснения; это не результаты измерений реальной библиотеки или конкретного сервера. Цель — объяснить, какой ответ и когда можно использовать повторно, а не предлагать удалить все кеши.

1. Хранить ли ответ, проверять ли его и с кем делиться

Читая политику кеширования, отдельно запишите три вопроса: можно ли сохранить ответ, можно ли сразу использовать сохранённую копию для следующего запроса и можно ли делиться ею между пользователями? Разрешение на хранение не означает неограниченного повторного использования, а проверка актуальности не разрешает делиться ответом с другими. Стандарт HTTP-кеширования RFC 9111 задаёт эти условия отдельными директивами. Далее рассматриваются директивы ответа без дополнительных аргументов с именами полей.

Вопрос для решенияДиректива ответаЧто нужно различать
Запрещено ли сохранять ответ?no-storeУказание не сохранять его для последующего использования
Нужно ли проверять перед повторным использованием?no-cacheХранение возможно, но перед повторным использованием нужна успешная проверка
Можно ли делиться между пользователями?privateЗапрещает хранение в общем кеше, но не запрещает его полностью в частном

Например, если общедоступное расписание часто меняют по одному адресу, можно рассмотреть требование проверки перед использованием даже при наличии сохранённой копии. У персонализированных экранов уже условия совместного использования отличаются от условий публичного расписания. private относится к общему кешу и не заменяет вход в систему и проверку полномочий. Объединив разные цели в одну настройку, при ускорении ответа можно ошибиться в том, кому предназначена информация.

В таблице политики указывайте не только директиву, но и её причину: является ли расписание публичной информацией, требующей проверки изменений, остаётся ли содержимое логотипа постоянным и выдаются ли по одному адресу персональные данные. Это отправная точка классификации реальных ответов, а не готовая конфигурация для любого сайта. Нужно также различать, к какому хранилищу — браузеру, CDN или другому — применяется правило.

2. Не выбирать no-cache и no-store только по названию

Название no-cache легко принять за запрет хранения, но в ответе оно требует проверять сохранённую копию перед повторным использованием. Если сервер подтвердит отсутствие изменений, сохранённое тело можно использовать снова. no-store, напротив, указывает не сохранять этот ответ. Поскольку отличаются и сохраняемые данные, и проверка при следующем запросе, одинакового поведения двух настроек ожидать нельзя.

В кеше fresh означает состояние, в котором политика разрешает повторное использование без дополнительной проверки. Это не гарантия того, что владелец сайта за это время не менял содержимое. Если период повторного использования задан через max-age, сохранённый ответ может выбираться и после изменения оригинала внутри этого периода. Сначала определите допустимую задержку обновления и свяжите требование с директивой. Не копируйте произвольный долгий срок хранения как универсальное решение для производительности.

Руководство MDN по HTTP-кешированию объясняет, что добавление no-store в новый ответ не удаляет старый ответ, уже сохранённый для того же URL. Если старая копия ещё пригодна и за новым ответом не обращаются, новый заголовок тоже может не дойти. Не считайте no-store командой очистки всех кешей или достаточным условием конфиденциальности; проверьте также срок жизни имеющихся ответов и процесс обновления управляемых кешей.

3. Проследить повторный визит через ETag и 304

Пусть вымышленный адрес расписания /hours.json сначала сообщает о закрытии в 18:00. Ниже показан поясняющий формат HTTP/1.1, в котором оставлены только необходимые части; другие заголовки реального ответа опущены. hours-v1 — выбранный сервером идентификатор представления в этом примере, а не формула вычисления времени и не настоящий хеш файла.

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache
ETag: "hours-v1"

{"closes":"18:00"}

Если браузер сохранил этот ответ, в следующий раз он может передать значение ETag в заголовке If-None-Match условного запроса. Если сервер определит, что условие соответствует выбранному текущему представлению и изменений нет, он вернёт 304 Not Modified. Следующий блок — сокращённая запись запроса и ответа подряд. Он не означает повторную отправку JSON расписания после 304.

GET /hours.json HTTP/1.1
Host: library.example
If-None-Match: "hours-v1"

HTTP/1.1 304 Not Modified
Cache-Control: no-cache
ETag: "hours-v1"

Как описано в документации MDN об ETag, клиент тогда использует сохранённое тело. У ответа 304 нет нового тела, однако запрос и проверка по-прежнему требуют обмена данными. Если закрытие перенесли на 19:00 и представление на сервере тоже изменилось, можно ожидать ответ 200 с новым телом и новым идентификатором на прежнее условие. Использование no-cache не гарантирует каждый раз 304 и не устраняет само по себе запросы к базе данных.

Проверять следует не один код состояния, а соответствие содержимого и идентификатора. Если содержимое изменилось, а сервер продолжает использовать старый ETag, проверка может дать неверный результат. Если же идентификатор постоянно меняется при том же содержимом, тело может пересылаться чаще. На сервере нужно проверить связь способа генерации с выбранным представлением; наличия ETag недостаточно для вывода о правильной реализации.

4. Отличать изменяемый документ от ресурса с новым именем

Документ вроде расписания, меняющийся по одному URL, и логотипы или скрипты, получающие новое имя при изменении содержимого, могут требовать разных стратегий. Например, если logo.a1.png заменяется на logo.b2.png, новый документ должен ссылаться на новый адрес. Добавив идентификатор к имени, но затем перезаписав старый файл, вы нарушите принцип совместного управления адресом и содержимым.

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

При развёртывании старые и новые документы некоторое время могут использоваться одновременно. Публикация нового документа до готовности нового ресурса или слишком раннее удаление старого ресурса создают отдельные сбои. В этом вымышленном примере можно проверить наличие файлов, на которые ссылается новый документ, и доступность файлов старого. Изменение имени — инструмент проектирования кеша, а не автоматическое решение всех вопросов порядка развёртывания и отката.

5. Проверять по одной гипотезе в панели Network

Начните непосредственную проверку с исходной записи при разрешённом кеше. Вместе изучите точный URL и строку запроса, версию расписания на экране, статус ответа, If-None-Match в запросе и Cache-Control с ETag в ответе. Даже одноимённые заголовки запроса и ответа задают условия разных сторон, поэтому фиксируйте, какую сторону читаете. Справочник Chrome DevTools Network показывает, как различать эти сведения в разделе Headers.

Вымышленный сценарий проверкиКакие записи сопоставитьКакой поспешный вывод неверен
Повторно запросить то же расписаниеУсловный запрос, статус, время на экранеРаз пришёл 304, обмена данными вообще не было
Изменить исходное время и запросить сноваНовое тело, ETag, фактический URLРаз показан успешный результат сохранения, все уже получили обновление
Сделать запрос с выключенным кешем браузераРазница первой загрузки и обычного повторного визитаРезультат равен скорости обычного повторного посещения
Вернуться кнопкой «Назад»Наличие нового запроса и восстановленный экранРаз появился экран, обязательно была новая HTTP-проверка

Затем отдельно испытайте отключение браузерного кеша. В Chrome настройка Disable cache действует, пока открыт DevTools, поэтому записывайте и состояние инструмента, и значение настройки. Это полезно для изучения первой загрузки, но не равно проверке использования сохранённой копии при обычном повторном посещении. Если не отметить включённую настройку, можно принять постоянное получение новых данных за неработающий кеш. Сохраните условия эксперимента, чтобы вернуться к разрешённому кешу и сравнить результаты.

Причину легче сузить, если не вносить несколько изменений и не отправлять много запросов одновременно. Сначала проверьте повторное посещение без изменения содержимого, затем измените один пункт времени и проследите ответ. Одновременная смена URL документа, настроек сервера и имени файла затрудняет определение причины результата. Если ожидаемых 200 или 304 нет, перечитайте фактические запрос и ответ, прежде чем добавлять настройки.

6. Проверить другие пути хранения и критерии завершения

Не предполагайте, что отключение HTTP-кеша браузера устраняет CDN перед сервером или другие пути хранения в приложении. Отдельно можно проверить, обрабатывает ли запрос service worker, какой ответ выбирает промежуточный сервер и не удерживает ли приложение на экране ранее полученные данные. Одинаковый URL не означает, что все уровни используют одну копию.

Возврат кнопкой «Назад» тоже нужно отличать от нового HTTP-запроса. При восстановлении экрана предыдущего сеанса браузер может не отправить ожидаемый запрос проверки даже при наличии no-cache. Если сразу счесть это доказательством игнорирования заголовка сервером, причину можно определить неправильно. Раздельная запись фактических запросов при новой навигации, обновлении и возврате помогает не объединять разные явления в одну проблему.

Критерий завершения для расписания — не только доля попаданий в кеш. Проверьте правильное использование сохранённой копии при отсутствии изменений, появление новой информации за допустимое время после изменения и корректный круг пользователей для общего ответа. Запись времени изменения и наблюдения, условий и фактического тела позволяет другим воспроизвести ситуацию. Если скорость выросла, но неверные часы работы видны долго, исходное требование не выполнено.

При внедрении в рабочую среду вместе проверяйте политику каждого типа ответа, обновление и откат. Не переносите указания кеширования публичного документа на персонализированный ответ и не считайте успешную проверку подтверждением прав доступа. Заголовки передают правила хранения и повторного использования. Когда можно объяснить, что было сохранено и какие проверки привели его к текущему экрану, устаревшую страницу удаётся диагностировать точнее.

Источники и материалы

Статья объясняет сведения из открытых источников. Упоминание организации не означает её проверки или одобрения.

Об издателе и контакты

Другие статьи по теме