Как настроить ETag с кешированием браузера
Я установил кеш браузера для статического сайта через .htaccess
файл путем установки:
# BROWER CACHING - 1 Day for images
<filesMatch ".(jpg|jpeg|gif|ico)$">
Header set Cache-Control "max-age=86400, public"
</filesMatch>
Я в порядке с этими изображениями, имеющими кэш на 1 день, но сайт часто меняется, и поэтому я не хочу кэшировать файлы CSS и JS.
Я читал об ETag, который, как я понимаю, позволяет кэшировать файл, а также устанавливать дату его создания, поэтому, если он будет обновлен при следующем посещении сайта клиентом, он проверит, совпадает ли дата создания.
- Правильно ли я понял ETag?
- Как мне это настроить? Я посмотрел вокруг, но не смог найти никакой информации о его конфигурации.
4 ответа
HTTP имеет несколько функций, связанных с кэшированием, и они применяются к кешу агента пользователя (браузера) и кешу прокси (прозрачным или нет; например, прокси в сети клиента или обратный прокси, расположенный рядом с сервером). Эти функции делятся на две группы: срок действия (может полностью запретить запрос) и проверка (может препятствовать передаче данных).
Тэг объекта (ETag
) является лишь одной из этих функций и относится к группе проверки. Другой в этой группе - время последней модификации (Last-Modified
). Тег Entity позволяет сделать недействительной кэш из-за изменения содержимого вместо более позднего времени последнего изменения. Узнайте больше о том, как тег сущности работает в Википедии. Короче говоря, типичное использование:
Сервер добавляет
ETag
заголовок ответа, содержащего обслуживаемый ресурс.Клиент кэширует ресурс и запоминает его тег сущности (значение
ETag
).В следующий раз, когда клиенту нужен ресурс, он запрашивает его с сервера условно. В запрос входит
If-None-Match
заголовок, содержащий тег сущности.Если ресурс изменился (тег объекта в
If-None-Match
сервер считается устаревшим), сервер отправляет ответ, содержащий текущую версию ресурса (и новый тег объекта), в противном случае он просто отвечает304 Not Modified
и не удосуживается отправить ресурс снова.
Для статических файлов (не создаваемых динамически с помощью сценария CGI или около того, при каждом запросе) Apache может быть настроен на генерацию ETag
с помощью FileETag
директиваПо умолчанию, без внесения каких-либо изменений в конфигурацию, Apache сгенерируетETag
и его значение будет основано на времени последнего изменения файла (mtime) и размере в Apache 2.4. В Apache 2.3.14 по умолчанию также используется номер индекса файла.
Если файл обслуживается динамически, Apache не может сгенерировать ETag
потому что он не знает подробности того, как генерируется ресурс для кэширования. Это зависит от сценария, чтобы установить ETag
соответственно и обрабатывать If-None-Match
, Например, в mod_perl If-None-Match
часть может быть обработана с помощью Apache2::Request::meet_conditions, которая реализует обработку условных запросов HTTP/1.1 в целом.
Если вы хотите полагаться исключительно на ETag, вы должны отключить другие функции проверки и механизм истечения срока действия. Задавать Cache-Control: max-age=0, must-revalidate
а также Expires: 0
провести повторную проверку записей в кэше (т.е. всегда делать запрос). Вы также можете удалить Last-Modified
заголовок из ответов, но HTTP/1.1 советует против этого, в целом.
Для сравнения Last-Modified
а также ETag
см. эти:
Обратите внимание, что Last-Modified
рассматривается как функция совместимости HTTP/1.0. ETag
может содержать одно и то же значение и работать точно так же (за исключением использования If-None-Match
вместо If-Modified-Since
).
В качестве дополнительного примечания я хотел бы добавить, что предлагаемый стандарт RFC 7232 существует и связан с деталями тегов сущностей и условных запросов. См. Приложение A для внесения изменений, внесенных в HTTP/1.1.
Вы бы использовали либо FileETag MTime Size
или же Header unset Etag
а также FileEtag none
, Не используйте оба (Создать ETag и Удалить ETag) и только выберите, какой из них лучше всего работает на вашем конкретном сервере.
# Create the ETag (entity tag) response header field
FileETag MTime Size
или же
# Remove the ETag (entity tag) response header field
Header unset ETag
FileETag none
ETAG не самый важный атрибут. Основной атрибут, который вы пропустили, истекает. Я уверен на 100%, кеш браузера будет работать без etag. Проверьте приведенную ниже конфигурацию на http://pisrs.si/. Как проверить? Нажмите F12 в браузере, перейдите на вкладку "Сеть", посмотрите, как загружаются ресурсы, сравните с вашим сайтом. Локальные ресурсы кэшируются по-разному. Проверьте информацию вашего браузера об этом.
Ниже приведена рабочая конфигурация из основного домена, которая работает. Убедитесь, что у вас включены необходимые моды.
<IfModule mod_mime.c>
AddType text/css .css
AddType application/x-javascript .js
AddType image/bmp .bmp
AddType image/gif .gif
AddType application/x-gzip .gz .gzip
AddType image/x-icon .ico
AddType image/jpeg .jpg .jpeg .jpe
AddType image/png .png
AddType application/x-font-ttf .ttf .ttc
AddType application/zip .zip
</IfModule>
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css A31536000
ExpiresByType application/x-javascript A31536000
ExpiresByType application/javascript A31536000
ExpiresByType text/javascript A31536000
ExpiresByType text/x-js A31536000
ExpiresByType image/bmp A31536000
ExpiresByType image/gif A31536000
ExpiresByType application/x-gzip A31536000
ExpiresByType image/x-icon A31536000
ExpiresByType image/jpeg A31536000
ExpiresByType application/x-font-otf A31536000
ExpiresByType image/png A31536000
ExpiresByType application/x-font-ttf A31536000
ExpiresByType application/zip A31536000
</IfModule>
<IfModule mod_deflate.c>
<IfModule mod_headers.c>
Header append Vary User-Agent env=!dont-vary
</IfModule>
AddOutputFilterByType DEFLATE text/html text/css text/x-component application/x-javascript application/javascript text/javascript text/x-js text/plain image/x-icon image/png image/gif
<IfModule mod_mime.c>
# DEFLATE by extension
AddOutputFilter DEFLATE js css htm html xml png gif
</IfModule>
</IfModule>
<FilesMatch "\.(gif|ico|jpg|jpeg|png|GIF|ICO|JPG|JPEG|PNG|css|js|woff|CSS|JS|WOFF|ttf|TTF)$">
<IfModule mod_headers.c>
Header unset Set-Cookie
Header set Cache-Control "max-age=31536000, public"
</IfModule>
</FilesMatch>
ETag - просто уникальный непрозрачный тег, вы не можете сравнивать их, за исключением равенства, поэтому, если у вас есть 2 ETag для одного и того же ресурса (например, URI), вы не можете сказать, какой ресурс более новый. Для этого вам нужен заголовок Last-Modified.
Даже заголовок Last-Modified проблематичен, так как он имеет разрешение только до 1 с, а на сильно модифицированных сайтах (например, популярных блогах) для кеша вполне возможно иметь несколько представлений файла с разными ETag и одинаковыми Last- Измененное значение. Жаль, что они не сочли нужным монотонно увеличивать ETag, чтобы их можно было сравнивать.
ETag используется в условных запросах с заголовком If-None-Match для GET и If-Match для PUT, и в первом случае сервер должен вернуть полное тело, только если ни один из предоставленных ETag не соответствует текущему ETag для ресурса (он изменился), а во втором случае (для PUT или PATCH), только если он совпадает, поэтому вы работаете над правильной версией.
ETag и Last-Modified являются заголовками валидатора кеша. Большая часть кеширования связана с концепцией свежести. Валидаторы позволяют вам проверить, действительна ли у вас версия, но для этого все равно требуется запросить сервер. Все, что вы можете сэкономить, это передача полезной нагрузки, и для многих вещей сегодня это просто не стоит.
Свежесть с другой стороны (заголовок Expires или директива max-age Cache-Control) позволяет клиенту избежать повторной проверки, если версия, которая у него уже есть, еще свежа (еще не истекла). Это экономит подключение к серверу для проверки и, таким образом, может сэкономить много времени при загрузке страниц.