Дополнительный инструмент, который поможет вам найти баланс между скоростью и актуальностью при обслуживании веб-приложения.
Что было отправлено?
stale-while-revalidate помогает разработчикам найти баланс между скоростью (немедленная загрузка кешированного контента) и актуальностью (обновление кешированного контента для последующего использования). Если вы поддерживаете сторонний веб-сервис или библиотеку, которые регулярно обновляются, или ваши собственные объекты имеют короткий срок службы, то stale-while-revalidate может стать полезным дополнением к существующим правилам кеширования.
Поддержка настройки stale-while-revalidate вместе с max-age в заголовке ответа Cache-Control доступна в Chrome 75 и Firefox 68.
Браузеры, которые не поддерживают stale-while-revalidate, будут игнорировать это значение конфигурации и использовать max-age. Подробнее об этом я расскажу далее.
Что это значит?
Давайте разобьем stale-while-revalidate на две части: идею о том, что кэшированный ответ может быть устаревшим, и процесс повторной проверки.
Во-первых, как браузер узнает, что кэшированный ответ устарел? Заголовок ответа Cache-Control, содержащий stale-while-revalidate, должен также содержать max-age. Количество секунд, указанное в max-age, определяет, когда контент считается устаревшим. Любой кешированный ответ, полученный после max-age, считается актуальным, а полученный до – устаревшим.
Если локально кэшированный ответ все еще актуален, его можно использовать как есть для выполнения запроса браузера. С точки зрения stale-while-revalidate в этом случае ничего делать не нужно.
Если же кешированный ответ устарел, выполняется ещё одна проверка: находится ли возраст кешированного ответа в пределах дополнительного временного окна, заданного параметром stale-while-revalidate?
Если возраст устаревшего ответа попадает в это окно, он будет использоваться для выполнения запроса браузера. В то же время в сеть будет отправлен запрос на повторную проверку, который не задержит использование кешированного ответа. Возвращенный ответ может содержать ту же информацию, что и ранее кешированный ответ, или отличаться от него. В любом случае ответ сети сохраняется локально, заменяя все, что ранее было кэшировано, и сбрасывая таймер "свежести", используемый при любых будущих сравнениях max-age.
Однако если устаревший кэшированный ответ достаточно старый и выходит за пределы временного окна stale-while-revalidate, он не выполнит запрос браузера. Вместо этого браузер получит ответ из сети и использует его как для выполнения первоначального запроса, так и для заполнения локального кеша свежим ответом.
Пример
Ниже приведен простой пример HTTP API, который возвращает текущее время, а точнее – количество минут, прошедших с начала часа.
В этом случае веб-сервер использует в HTTP-ответе следующий заголовок Cache-Control:
Cache-Control: max-age=1, stale-while-revalidate=59
Это означает, что если запрос времени повторится в течение следующей секунды, то ранее кешированное значение будет по-прежнему актуальным и будет использоваться как есть, без повторной проверки.
Если запрос повторяется в течение 1–60 секунд, кешированное значение будет устаревшим, но будет использоваться для выполнения запроса к API. В то же время в фоновом режиме будет отправлен запрос на повторную проверку, чтобы заполнить кеш новым значением для использования в будущем.
Если запрос повторяется более чем через 60 секунд, устаревший ответ не используется вообще, а выполнение запроса браузера и повторная проверка кеша будут зависеть от получения ответа из сети.
Ниже приведено описание этих трех состояний и указаны временные интервалы, в течение которых они действуют в нашем примере.
В каких случаях обычно используется этот параметр?
Хотя приведенный выше пример с API-сервисом, возвращающим минуты, прошедшие с начала часа, является надуманным, он иллюстрирует ожидаемый вариант использования – сервисы, которые предоставляют информацию, требующую обновления, но для которых допустима некоторая степень устаревания.
Более реалистичные примеры – API для получения текущих погодных условий или главных новостей за последний час.
Как правило, любой ответ, который обновляется с известным интервалом, скорее всего, будет запрашиваться несколько раз и является статическим в пределах этого интервала, является хорошим кандидатом для краткосрочного кэширования через max-age. Использование stale-while-revalidate в дополнение к max-age повышает вероятность того, что будущие запросы могут быть выполнены из кеша с более свежим контентом, не блокируя ответ сети.
Как он взаимодействует с сервис-воркерами?
Если вы слышали о stale-while-revalidate, то, скорее всего, в контексте рецептов, используемых в сервис-воркере.
Использование stale-while-revalidate через заголовок Cache-Control имеет некоторые сходства с его использованием в сервис-воркере, и применяются многие из тех же соображений относительно компромиссов в отношении свежести и максимального времени жизни. Однако при выборе между сервис-воркером и заголовком Cache-Control нужно учитывать несколько факторов.
Используйте подход с сервис-воркером, если:
- Вы уже используете сервис-воркер в своем веб-приложении.
- Вам нужен детальный контроль над содержимым кеша и вы хотите реализовать что-то вроде политики истечения срока действия, основанной на принципе "наименее недавно использованный". В этом вам поможет модуль Cache Expiration в Workbox.
- Вы хотите получать уведомления, когда устаревший ответ меняется в фоновом режиме на этапе повторной проверки. В этом вам поможет модуль Broadcast Cache Update из Workbox.
- Такое поведение
stale-while-revalidateнеобходимо во всех современных браузерах.
Используйте подход Cache-Control, если:
- Вы не хотите тратить время на развертывание и обслуживание сервисного работника для своего веб-приложения.
- Вы не против, чтобы автоматическое управление кешем браузера предотвращало чрезмерное увеличение локального кеша.
- Вы готовы использовать подход, который пока поддерживается не во всех современных браузерах (по состоянию на июль 2019 г.; в будущем поддержка может быть расширена).
Если вы используете сервис-воркер и у вас также включен stale-while-revalidate для некоторых ответов через заголовок Cache-Control, то сервис-воркер, как правило, будет иметь "первую попытку" ответить на запрос. Если сервисный работник решит не отвечать или в процессе генерации ответа сделает сетевой запрос с помощью fetch(), то вступит в силу поведение, настроенное с помощью заголовка Cache-Control.
Подробнее…
stale-while-revalidateresponse в спецификации Fetch API.- RFC 5861, в котором содержится исходная спецификация
stale-while-revalidate. - HTTP-кеш: первая линия обороны (из руководства по надежности сети на этом сайте).