Статьи Архив статей

Перевод: Мациевский Николай aka sunnybear
Опубликована: 12 июля 2009

Перезагружаем XHR-запросы

Примечание: ниже находится перевод заметки "F5 and XHR deep dive", в которой Steve Souders исследует кэширующее поведение XHR-запросов для различных браузеров. Мои комментарии далее курсивом.

Недавно в заметке Ajax Caching: Two Important Facts из блога HttpWatch было высказано следующее утверждение:

«любые данные, полученные при помощи Ajax, никогда не будут обновлены в IE прежде истечения срока действия кэша, даже если вы форсируете обновление (Ctrl+F5). Единственный путь обновить эти данные — это вручную удалить их из кэша.»

Это было весьма обескураживающе для меня, но это оказалось правдой. Если вы нажимаете Перезагрузку (F5), IE перезапросит все ресурсы (даже с неистекшим сроком действия кэша), за исключением XHR. Это может вызвать большое недоумение среди разработчиков при тестировании, но меня заинтересовало, какие еще проблемы существуют в этом направлении. Будет ли поведение аналогичным во всех остальных основных браузерах? Что произойдет, если срок давности кэша будет в прошлом, или заголовок Expires вообще не будет выставлен? Будет ли какой-либо эффект от добавления Cache-Control max-age (который переписывает заголовок Expires)?

Проводим тестирование

Для этого была создана специальная страниц для тестирования кэширования Ajax.

На тестовой странице располагается картинка, внешний скрипт и XMLHttpRequest. Срок действия кэша определяется выбором соответствующей ссылки.

  • Expires в прошлом добавляет в ответ заголовки Expires, который содержит дату на 30 дней ранее текущей, и Cache-Control с max-age=0.
  • Без Expires вообще не выставляет никаких заголовков Expires или Cache-Control.
  • Expires в будущем добавляет заголовки Expires, который содержит дату на 30 больше текущей, и Cache-Control с max-age=2592000.

Тест очень простой: просто перейдите по ссылке (например, Expires в прошлом), дождитесь полной загрузки, а затем нажимайте F5. В таблице 1 приведены результаты тестирования этой страницы в основных браузерах. В таблице записано перезапрашивался ли XHR-ресурс или был прочитан из кэша, а также если перезапрашивался, то с каким кодом HTTP-статуса.

Результаты

Expires в прошломБез ExpiresExpires в будущем
Chrome 2304304304
Firefox 3.5304304304
IE 7304кэшкэш
IE 8304кэшкэш
Opera 10304кэш304
Safari 4200200200

Таблица 1. Если кэшируется XHR, что происходит при нажатии F5?

Ниже приведены мои соображения на тему того, что происходит при нажатии F5:

  • Все браузеры перезапрашивают и картинку, и внешний скрипт. (Это имеет смысл.)
  • Все браузеры перезапрашивают XHR-ресурс, если срок действия кэша находится в прошлом. (Это тоже имеет смысл: браузер знает, что закэшированный XHR-ресурс устарел.)
  • Единственное различие в поведение происходит в тот момент, когда для XHR-ресурса нет заголовка Expires, или же Expires выставлен в будущее. IE 7&8 не перезапрашивают XHR-ресурс, если нет Expires или Expires выставлен в будущее, даже при нажатии Ctrl-F5. Opera 10 не перезапрашивает XHR-ресурс, если нет Expires. (Эквивалента для Ctrl-F5 в Opera найти не удалось.)
  • И Opera 10, и Safari 4 перезапрашивают favicon.ico во всех случаях. (Это выглядит весьма растратно.)
  • Safari 4 не посылает заголовок If-Modified-Since во всех случаях. В результате ответ всегда приходит со статус-кодом 200 и включает запрашиваемый ресурс полностью. Это верно как для XHR-ресурса, так и для картинок и внешних скриптов. (Это выглядит неоптимально и отличается от поведения других браузеров.)

Выводы

Ниже я постарался резюмировать свои рекомендации, что следует вынести как веб-разработчикам, так и производителям браузеров из этой ситуации:

  1. Разработчики должны выставлять срок действия кэша для XHR-ресурсов или в прошлом, или в будущем, чтобы предотвратить расхождения в поведении браузеров, когда Expires вообще не выставлен.
  2. Если XHR-ресурсы вообще не должны быть закэшированы, разработчикам стоит выставлять дату изменения ресурса в прошлое. Это давняя проблема с различным поведением браузеров при наличии закэшированных копий определенных ресурсов, и касается она не только XHR-запросов. Например, не всегда пользователи будут перезагружать страницу, они могут на нее попасть, просто переходя по ссылкам. В этом случае браузер выдаст им закэшированные версии XHR. Для форсирования сброса кэша мы можем выставлять, например, дополнительный GET-параметр. И это будет работать для всех браузеров и всех прокси-серверов.
  3. Если XHR-запросы желательно кэшировать, то разработчики должны назначить срок истечения кэша в будущем. При тестировании в IE 7&8 разработчикам придется не забывать очищать кэш, чтобы проверить действие Перезагрузки (F5).
  4. IE должен перезапрашивать XHR-ресурс при нажатии F5.
  5. Opera и Safari должны прекратить перезапрашивать favicon.ico при нажатии F5.
  6. Safari должен посылать заголовок If-Modified-Since для XHR-ресурсов при нажатии F5.

Читать дальше

Все комментарии (habrahabr.ru)