barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)
Показаны сообщения с ярлыком cache. Показать все сообщения
Показаны сообщения с ярлыком cache. Показать все сообщения

вторник, 21 июня 2016 г.

requirejs и управление браузерным кэшированием с помощью конфигурационного параметра urlArgs

Задача

В проекте, использующем requirejs, встала острая необходимость управлять кэшированием js-файлов браузером. Ситуация типичная: в приложении обновляется некоторый js-файл, но клиент продолжает пользоваться старой версией файла, т.к. браузер его закэшировал (в т.н. называемый Back/Forward Cache, или BFCache: http://www.pvsm.ru/javascript/61476). И пока кэш не просрочится, ситуация не изменится. Вот как данный случай выглядит в Firebug:


Причем данная ситуация может возникать как в продуктивном развертывании, так и при разработке / отладке, и ее нужно как-то брать под свой контроль, т.к. заставлять пользователя чистить кэш - не лучшее решение.

Решение

Конечно, управлять кэшированием можно на стороне сервера, с помощью заголовков Expires / Last-Modified / Cache-Control / Pragma. Но, во-первых, предлагаемый здесь способ более гибкий. А, во-вторых, если управлять кэшированием вы решили не на самом старте проекта, а лишь в какой-то момент его жизни после выхода в продакшен, вы никакими серверными махинациями не заставите браузер раскэшировать то, что он уже закэшировал ранее.
Итак, про requeirejs. Конфигурация requirejs имеет параметр urlArgs, позволяющий добавлять GET-аргументы к URL-ам, по которым загружаются js-файлы. Например, при задании этого параметры равным "v=1" файл formatter.js будет грузиться по URL'у formatter.js?v=1. В новых версиях requirejs есть возможность использовать функцию вместо статичной строки, но сейчас не об этом. Главное, что для браузера formatter.js и formatter.js?v=1 - различные  URL, и даже закешировав ранее файл formatter.js браузер все равно пойдет на сервер за formatter.js?v=1 (хотя, сервер, конечно, по обоим URL'ам выдаст один и тот же файл, т.к. это статичный ресурс и GET-параметры для него игнорируются).
При поиске решения я наткнулся на интересную статью: http://blog.johnnyreilly.com/2014/03/caching-and-cache-busting-with-requirejs.html. В ней приводится рекомендация по использованию параметра urlArgs для управления кэшированием, которую я успешно и применил. Автор предлагает 2 разных подхода для разработки и продуктивного развертывания проекта:
  • В процессе разработки удобно, когда вообще ничего не кэшируется, и любые правки на сервере сразу же попадают в браузер. В данном случае задаем параметр urlArgs равным "v=" +  (new Date()).getTime(). В итоге имеем при каждой загрузке страницы новые URL'ы, и браузер все js-файлы гарантированно загружает с сервера
  • В продуктивном развертывании необходим баланс между актуальностью файлов и потреблением сетевых ресурсов, так что вариант, описанный выше, не подходит: файлы на сервере меняются не часто, и на какой-то промежуток времени их все же хорошо было бы кэшировать. Здесь можно воспользоваться следующим подходом: устанавливаем параметр urlArgs  равным "v=<productVersion>", где <productVersion> - версия Вашего продукта (сайта). Т.о., при выпуске и установке в продуктив новой версии Вашего продукта все клиенты при первом обращении к сайту получат актуальные версии js-файлов, т.к. изменилась версия продукта, а, значит, и все URL-ы, по которым загружаются js-ки. Далее же, до выхода следующей версии, браузер может (и будет) спокойно кэшировать js-файлы, т.к. они гарантированно остаются неизменными.

вторник, 17 января 2012 г.

IE, загрузка файлов и Cache-Control: no-cache, no-store

Проблема:
Заголовок "Cache-Control: no-cache, no-store", предусмотренный в HTTP/1.1 для предотвращения кэширования информации браузерами и прокси-серверами, будучи установленным для ответа, отсылающего файл, вызывает у Internet Explorer появление сообщения (правда не в 100% случаев, я так и не нашел закономерности):
"Не удалось открыть этот интернет-узел. Запрошенный узел недоступен или не найден..."
и файл, естественно, не загружается.

Решение:
Ничего не поделаешь, для файлов заголовок "Cache-Control: no-cache, no-store" придется не ставить. Впрочем, я думаю IE и так не будет кэшировать файлы =)

среда, 28 декабря 2011 г.

Отключение кэширования данных браузером или прокси-сервером с помощью заголовков HTTP

Кэширование данных браузером и прокси-сервером отключается следующими 4 заголовками:
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Last-Modified: <now>
, где <now> - текущая дата и время. В JSP (и вообще в любом HTTP-сервлете) это можно установить следующим образом:
DateFormat fullDateTimeFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", new Locale("EN"));
response.setHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
response.setHeader("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("Last-Modified", fullDateTimeFormat.format(new java.util.Date()));