Каковы оптимальные HTTP-заголовки, связанные с кэшем, для содержимого, которое может измениться?
У нас есть несколько файлов, которые обслуживаются через HTTP и которые время от времени меняются.
Какие заголовки HTTP, связанные с кэшированием, мы должны вернуть в ответе HTTP, чтобы оптимизировать скорость загрузки браузера, в то же время заставляя браузер проверять наличие последней версии файла?
Мы уже устанавливаем заголовок "Истекает" с датой в прошлом (кажется, на данный момент существует консенсус).
Но тогда некоторые люди рекомендуют установить этот заголовок:
Cache-Control: no-cache, no-store, must-revalidate
Но проблема с этим заголовком заключается в том, что он запрещает браузеру сохранять локальную копию файла, поэтому файл загружается каждый раз, даже если он не изменяется, с кодом ответа 200.
Если я просто использую:
Cache-Control: no-cache
Затем браузер (по крайней мере, Firefox 14 и Chrome 20) хранит локальную копию, отправляет If-Modified-Since
а также If-None-Match
заголовки, и сервер возвращает код 304, а содержимое файла не загружается. Это оптимальное поведение для этих файлов, которое может измениться в любое время.
Проблема в том, что я не знаю, достаточно ли просто установки "no-cache", чтобы заставить все браузеры (включая старые, но все еще используемые версии) и прокси-серверы повторно проверять свою локально кэшированную копию с сервером.
Наконец, как насчет Pragma: no-cache
заголовок? Должен ли он быть включен в HTTP-ответ тоже?
3 ответа
Документация разработчиков Google содержит отличную документацию по кешированию и предоставляет несколько полезных шаблонов для использования.
Например, у него есть блок-схема для определения оптимальной политики управления кэшем.
Кроме того, он определяет хороший шаблон для добавления отпечатка пальца к файлам и установки срока действия на более длительное время, например, на год.
- Локально кэшированные ответы используются до истечения срока действия ресурса
- Внедрение отпечатка содержимого файла в URL-адрес позволяет нам заставить клиента обновиться до новой версии ответа.
- Каждое приложение должно определить свою собственную иерархию кэша для оптимальной производительности
Возможность определения политик кэширования для каждого ресурса позволяет нам определять "иерархии кэширования", которые позволяют нам контролировать не только продолжительность каждого кэширования, но также и скорость, с которой посетители видят новые версии. Например, давайте проанализируем приведенный выше пример:
- HTML-код помечен как "без кэширования", что означает, что браузер всегда будет повторно проверять документ при каждом запросе и извлекать последнюю версию, если содержимое изменится. Кроме того, в разметке HTML мы встраиваем отпечатки пальцев в URL для ресурсов CSS и JavaScript: если содержимое этих файлов изменится, то изменится и HTML-код страницы, и будет загружена новая копия ответа HTML.
- CSS разрешено кэшировать браузерами и промежуточными кешами (например, CDN), и срок его действия истекает через 1 год. Обратите внимание, что мы можем использовать
"далекое будущее истекает" 1 год безопасно, потому что мы встраиваем файл
Отпечатайте его имя файла: если CSS обновлен, URL изменится
также.- Срок действия JavaScript также истекает через 1 год, но он помечен как закрытый, возможно, потому что он содержит некоторые личные данные пользователя, которые
CDN не должен кэшироваться.- Изображение кэшируется без версии или уникального отпечатка и истекает через 1 день.
Комбинация ETag, Cache-Control и уникальных URL-адресов позволяет нам предоставлять лучшее из всех миров: долгое время истечения срока действия, контроль над тем, где можно кэшировать ответ, и обновления по требованию.
Лучший способ, возможно, не на 100% соответствующий вашим потребностям:
Cache-Control:max-age=315360000, public
Expires:Tue, 23 Aug 2022 10:53:13 GMT
И дайте файлу "зависимое от содержимого имя файла", такое как stylesheet_v32.css. Как только содержимое изменится, измените имя файла + ссылку на, и браузер получит последнюю версию. Если имя файла остается, браузер не должен запрашивать его.
Это безопасно и согласованно во всех браузерах.
Надеется Cache-Control: no-cache
и браузеры, сохраняющие его в любом случае, - это то, что я не хотел бы делать.
Я нашел два способа принудительно перепроверить кеш клиентом:
Cache-Control: max-age=0, must-revalidate
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Это работает по крайней мере с Firefox. Я полагаю, что IE и Chrome также будут правильно реагировать. Он должен работать со старыми браузерами, использующими HTTP/1.0.
С HTTP 1.1 вы можете использовать ETag
, В этом случае must-revalidate
опция не нужна, потому что ETag
достаточно, чтобы клиент реагировал так, как будто must-revalidate
был здесь:
Cache-Control: max-age=0
ETag: 123
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Это скажет клиенту создать кеш-версию данных с ETag
123 и перепроверять сервер каждый раз, когда ему нужна копия этих данных. Затем вы можете ответить с 304 Not Modified
,
Два варианта, которые вы окончательно не можете использовать: no-cache
а также no-store
,
Если вы хотите предотвратить кэширование данных промежуточными кешами, обязательно добавьте private
к Cache-Control
опции.
В качестве интересной функции вы также можете использовать небольшой максимальный возраст, например, несколько минут, чтобы позволить клиенту кэшировать данные за это время, а затем отправить GET
на который вы можете ответить 304
:
Cache-Control: max-age=300
ETag: 123
Expires: Tue, 29 Mar 2015 15:05:00 GMT
В этом случае браузер не будет проверять новые данные в течение 5 минут. После этого он отправляет вам If-None-Match: 123
,