Чтобы ответить на ваш вопрос о том, почему кеширование работает, хотя веб-сервер не включает заголовки:
- Истекает:
[a date]
- Cache-Control: max-age =
[seconds]
Сервер любезно попросил любые промежуточные прокси не кэшировать содержимое (т.е. элемент должен кэшироваться только в частном кэше, т.е. только на вашем локальном компьютере):
Но сервер забыл включить любые подсказки кэширования:
- они забыли включить Expires , поэтому браузер знает, что использовать кэшированную копию до этой даты
- они забыли включить Max-Age , поэтому браузер знает, как долго кэшируемый элемент хорош
- они забыли включить E-Tag , чтобы браузер мог сделать условный запрос
Но они включили дату последнего изменения в ответ:
Last-Modified: Tue, 16 Oct 2012 03:13:38 GMT
Поскольку браузер знает дату, когда файл был изменен, он может выполнить условный запрос . Он запросит файл у сервера, но прикажет серверу отправлять файл, только если он был изменен с 2012/10/16 3:13:38:
GET / HTTP/1.1
If-Modified-Since: Tue, 16 Oct 2012 03:13:38 GMT
Сервер получает запрос, понимает, что у клиента уже самая последняя версия. Вместо того, чтобы отправлять клиента 200 OK
, а затем содержимое страницы, вместо этого он сообщает, что ваша кэшированная версия хороша:
304 Not Modified
Ваш браузер должен был перенести задержку отправки запроса на сервер и дождаться ответа, но он избавил от необходимости повторно загружать статический контент.
Почему Макс-Эйдж ? Почему истекает ?
Потому что Last-Modified отстой.
Не все на сервере имеют дату, связанную с ним. Если я создаю страницу на лету, дата с ней не связана - сейчас . Но я совершенно готов позволить пользователю кэшировать домашнюю страницу на 15 секунд:
200 OK
Cache-Control: max-age=15
Если пользователь забьет F5, он получит кэшированную версию в течение 15 секунд. Если это корпоративный прокси-сервер, то все 67198 пользователей, попадающих на одну и ту же страницу в одном и том же 15-секундном окне, получат одинаковое содержимое - все из закрытого кэша. Спектакль победит всех.
Преимущество добавления Cache-Control: max-age
заключается в том, что браузер даже не должен выполнять условный запрос.
- если вы указали только
Last-Modified
, браузер должен выполнить запрос If-Modified-Since
и следить за 304 Not Modified
ответом
- если вы укажете
max-age
, браузеру даже не придется страдать в сети; контент выйдет прямо из кеша
Разница между "Cache-Control: max-age" и "Expires"
Expires
является устаревшим эквивалентом современного (c. 1998) Cache-Control: max-age
заголовка:
Expires
: вы указываете дату (гадость)
max-age
: вы указываете секунды (доброта)
И если оба указаны, то браузер использует max-age
:
200 OK
Cache-Control: max-age=60
Expires: 20180403T192837
Любой веб-сайт, написанный после 1998 года, не должен Expires
больше использоваться , а должен использоваться max-age
.
Что такое ETag?
ETag похож на Last-Modified , за исключением того, что он не обязательно должен быть датой - он просто должен быть чем-то .
Если я вытаскиваю список продуктов из базы данных, сервер может отправлять последние rowversion
как ETag, а не как дату:
200 OK
ETag: "247986"
Мой ETag может быть хешем SHA1 статического ресурса (например, изображения, js, css, шрифта) или кэшированной визуализированной страницы (то есть, именно это и делает вики Mozilla MDN; они хэшируют окончательную разметку):
200 OK
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
И так же, как в случае условного запроса на основе Last-Modified :
GET / HTTP/1.1
If-Modified-Since: Tue, 16 Oct 2012 03:13:38 GMT
304 Not Modified
Я могу выполнить условный запрос на основе ETag:
GET / HTTP/1.1
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
304 Not Modified
An ETag
превосходит, Last-Modified
потому что он работает для вещей помимо файлов , или вещей, которые имеют понятие даты . Это как раз является