Использование AppCache для локального сохранения ресурсов

С появлением в W3C HTML5 кэша приложений, стало возможно выполнение приложения Web в автономном режиме, также как и в сети.

Автономное хранилище HTML5 определяет метод сохранения файлов в кэш-памяти, чтобы когда пользователь не подключен к сети, браузер имел, тем не менее, доступ к необходимым файлам. Это могут быть файлы HTML, CSS или JavaScript, или любые другие ресурсы необходимые сайту для работы.

HTML5 для автономных приложений web использует новое средство, называемое кэшем приложений, или коротко AppCache. Сохраняемые в этом AppCache файлы доступны для приложения, даже когда пользователь не находится в сети. С помощью файла манифеста можно определить, какие файлы необходимо сохранить в AppCache.

Существует ряд особенностей, которые отличают AppCache от обычного кэша браузера. Прежде всего, они решают различные задачи. AppCache предназначен для подходящих приложений Web, в то время как кэш браузера предназначен вообще для обычных страниц web. Обычная кэш-память будет кэшировать почти любую страницу, в то время как AppCache будет кэшировать только те страницы, которые специально указаны в файле манифеста. Кроме того, обычный кэш ненадежен, так как мы не знаем, какие страницы (и какие ресурсы этих страниц) будут наверняка доступны.

Преимущество использования AppCache состоит в том, что теперь разработчик имеет значительно больше программного контроля над кэшем, что означает значительно больше уверенности и контроля над тем, как приложения Web будут вести себя в автономном режиме. Отметим также, что можно иметь несколько страниц, совместно использующих одну память AppCache. Также с помощью AppCache можно использовать API для определения состояния памяти AppCache, и затем даже заставить ее обновиться.
Файл манифеста находится на сервере и указывает, какие файлы должны храниться на клиентской стороне в AppCache браузера, готовые к тому, что пользователь переходит в автономный режим.

Для файла манифеста можно задать любое имя, но рекомендуется давать ему расширение .manifest. Каждый файл манифеста должен начинаться с CACHE MANIFEST, после чего перечисляются файлы, которые желательно сохранить и сделать доступными для автономного использования. Можно задавать комментарии, помещая # в начале строки. Очень простой файл манифеста выглядит следующим образом:

CACHE MANIFEST
#Можно также использовать заголовок раздела CACHE:, 
#чтобы явно объявить три следующих файла.

style.css
script.js
index.htm

Файл манифеста должен иметь правильный тип MIME, который должен быть text/cache-manifest. Чтобы сделать это, можно задать расширение .manifest для файла манифеста, и добавить следующую строку в файл .htaccess на сервере:

AddType text/cache-manifest .manifest

Теперь, после создания файла манифеста, говорящего какие файлы необходимо кэшировать в приложении, нужно сообщить странице HTML, чтобы она использовала этот кэш. Для этого нужно соединить страницу с файлом манифеста, включая атрибут manifest в тег <HTML> страницы. Например:

<html manifest="demo.manifest">

Если приложение Web имеет более одной страницы, необходимо сделать так, чтобы все страницы соединялись с файлом манифеста таким образом, иначе они не будут частью AppCache, и не будут работать автономно.

CACHE:

До сих пор мы видели самый простой пример использования файла манифеста. С помощью заголовков разделов можно в действительности точно задать, что определенный файл должен кэшироваться или нет.

Можно использовать заголовок раздела CACHE: для явного объявления, какие файлы необходимо кэшировать. Например, предыдущий пример файла манифеста можно написать следующим образом, и он будет функционировать точно таким же образом:

CACHE MANIFEST

CACHE:
style.css
script.js
index.htm

Единственное различие состоит в том, что в этом примере мы явно объявили, что все эти файлы будут частью кэша приложений.

Простой пример страницы, которая использует заголовок раздела CACHE:.

Важно отметить, что указанный для файлов путь доступа должен задаваться относительно расположения файла манифеста. В примере здесь мы предполагаем, что упомянутые файлы находятся в том же каталоге, что и файл манифеста. Можно использовать как относительные, так и абсолютные URL при указании файлов в файле манифеста.

Файлы, определенные как часть CACHE:, будут загружаться из AppCache (а не с сервера), даже если вы находитесь в сети, при условии, что в файле манифеста нет изменений. Если, однако, браузер, найдет обновленный файл манифеста, то новый кэш будет снова загружен однократно, в соответствии с тем, что говорит новый файл манифеста. Поэтому AppCache может быть неподходящим для сайтов с быстро изменяющимся контентом, таким как новостные блоги, например, но может быть очень полезен для приложений Web, которые делают определенную работу и могут работать автономно (например, приложение календаря, или список дел, и т.д.).

NETWORK:

Если страница связана с файлом манифеста, то только упомянутые в манифесте файлы будут пытаться загрузиться, независимо от того находится пользователь в сети или нет. Однако могут возникать ситуации, когда требуется, чтобы какой-то файл не соединялся с кэшем, когда пользователь находится в сети, а чтобы он соединился и загрузил свежие данные с сервера вместо кэша (Например, некоторый динамический контент из сценария CGI).

По сути, если страница связана с файлом манифеста, то весь сетевой трафик ее файлов блокируется, и файлы либо должны загружаться из AppCache, либо отказываться загружаться. Заголовок раздела NETWORK: делает исключения для этого правила. Можно использовать раздел заголовка NETWORK: для объявления, какие файлы не должны кэшироваться, чтобы они загружались с сервера, и никогда не были частью кэша приложений. Раздел заголовка NETWORK: принимает во внимание заголовок обычного кэша браузера. Поэтому, если предполагается, что файл будет кэшироваться обычным кэшем браузера, то он и будет им кэшироваться (также как и любой другой файл, не определенный в AppCache), даже если он определен под заголовком раздела NETWORK:.

CACHE MANIFEST

CACHE:
style.css
script.js
index.htm

NETWORK:
style2.css

В примере выше style2.css всегда будет загружаться с сервера и никогда не будет частью кэша приложений. Помните, что могут быть ситуации, когда имеется слишком много файлов для перечисления, которые не должны использовать кэш, что делает запись всех этих файлов под заголовком раздела NETWORK: обременительным. В этом случае можно использовать символ звездочки (*), что разрешает всем URL выходить в сеть, если вы находитесь в сети.

Посмотрите на пример, который использует файл манифеста с заголовком раздела NETWORK:. Можно заметить, что когда вы не в сети и перезагружаете страницу, страница перезагружается, но оформление фона исчезает. Это связано с тем, что оформление фона в этом примере находится в файле style2.css, который находится под заголовком раздела NETWORK:, что означает, что он не кэшируется и будет загружаться, только когда вы в сети и перезагружаете страницу.

FALLBACK:

Раздел заголовка FALLBACK: используется для определения запасных ресурсов, которые будут использоваться вместо файлов, которые отказываются загружаться (или загружаются не полностью):

CACHE MANIFEST

CACHE:
style.css
script.js
index.htm

NETWORK:
style2.css

FALLBACK:
main_image.jpg backup_image.jpg

Предполагается, что резервный контент будет кэшироваться и будет использоваться только в том случае, когда основной контент не загружается. В приведенном выше примере файл backup_image.jpg кэшируется в AppCache, поэтому когда файл main_image.jpg не может загрузиться, на его место будет загружаться backup_image.jpg. Посмотрите пример с резервной копией манифеста — если перейти на эту страницу, и отсоединиться от Интернет, а затем перезагрузить страницу, браузер попытается загрузить изображение, но так как вы не в сети (и изображение не кэшировано) оно не будет загружено, и, следовательно, на его место будет загружен резервный контент. (Браузер сначала в течение некоторого времени будет пытаться загрузить основной контент, и только затем загрузит резервный контент ... так что будьте терпеливы!)

Файл манифеста, который используется в этом примере, предоставляет резервный контент для нескольких изображений.

Программный контроль над кэшем приложений

Одним из больших достоинств кэша приложений является то, что теперь программист имеет доступ к тому, как себя должен вести кэш. Он имеет доступ к событиям, которые могут сообщить о текущем состоянии кэша приложений, и имеет также функции для асинхронного обновления. Например, можно использовать функцию window.applicationCache, чтобы определить, поддерживает браузер кэш приложений или нет. Давайте посмотрим на некоторые другие способы, которыми можно получить программный контроль над кэшем приложений.

Статусы

Текущий статус кэша приложений можно проверить с помощью функции window.applicationCache.status, которая возвращает числовое значение, соответствующее следующим статусам:
  • 0 - uncached (не кэшировано). Если страница не соединена с кэшем приложений. Также при самой первой загрузке кэша приложений и во время загрузки AppCache будет иметь статус uncached.
  • 1 – idle (не работает). Когда браузер имеет самую последнюю версию AppCache, и нет обновленных версий для загрузки, то статус задается как Idle.
  • 2 – checking (проверка). В течение времени, когда страница проверяет наличие обновленного файла манифеста, статус задается как Checking.
  • 3 – downloading (загрузка). В течение времени, когда страница фактически загружает новый кэш (если был обнаружен обновленный файл манифеста), статус задается как downloading
  • 4 – updateready (обновление готово). Когда браузер заканчивает загрузку нового кэша, он готов к использованию (но все еще не используется). В течение этого времени статус задается как updateready
  • 5 – obsolete (устарел). Когда файл манифеста невозможно найти, статус задается как obsolete, и кэш приложений удаляется. Важно знать, что когда файл манифеста (или любой из файлов, упомянутых в манифесте, за исключением имеющих резервные копии) отказывается загружаться, то это будет считаться ошибкой и будет продолжать использоваться старый кэш приложений.

События

В зависимости от того, что происходит с AppCache в данный момент, могут порождаться также некоторые события.
  • Checking (проверка). Это событие порождается, когда браузер выполняет проверку, пытаясь загрузить манифест в первый раз, или проверяет, что имеется обновленная версия файла манифеста.
  • Noupdate (нет обновления). Если на сервере отсутствует обновленная версия файла манифеста, порождается событие noupdate.
  • Downloading (загрузка). Если браузер загружает кэш в первый раз, или загружает обновленную версию, порождается это событие.
  • Progress (успешно). Это событие порождается для каждого файла, который загружается как часть AppCache.
  • Cached (кэшировано). Это событие порождается, когда все ресурсы закончили загрузку, и приложение будет кэшировано.
  • Updateready (обновление готово). Когда ресурсы закончили перезагрузку обновленного кэшированного файла, вызывается updateready. Когда это произошло, можно использовать swapCache() (как объясняется далее в статье), чтобы заставить браузер использовать этот вновь обновленный кэш.
  • Obsolete (устарел). Это событие порождается, если файл манифеста невозможно найти (ошибка 404 или 410).
  • Error (ошибка). Это событие может порождаться по различным причинам. Если файл манифеста невозможно найти, процесс загрузки кэша приложений должен быть прерван, и в данном случае может порождаться это событие. Оно может порождаться в случае наличия файла манифеста, но какой-нибудь из файлов, упомянутых в файле манифеста, не может быть загружен правильно. Оно может порождаться даже в случае изменений файла манифеста во время выполнения обновления (в этом случае браузер будет ждать какое-то время, прежде чем попытаться еще раз), или в любом другом случае, где возникает фатальная ошибка.
Все обработчики событий для этих событий имеют префикс 'on'. Например, onchecking, onupdateready, onerror, и т.д.

Функции

API кэша приложений имеет несколько особенностей, которые стоит упомянуть:
  • window.applicationCache.update(): Эта функция будет запускать процесс загрузки кэша приложений, который является почти тем же, что и перезагрузка страницы. Она просто проверяет, изменился ли манифест, и, если возможно, загружает свежую версию всего контента в кэше (учитывая все заголовки кэша). Отметим, что даже хотя при этом создается новый кэш, страница будут продолжать использовать старый кэш. Чтобы заставить страницу использовать только что загруженный новый кэш, необходимо использовать функцию swapCache().
  • window.applicationCache.swapCache(): Эта функция приказывает браузеру начать использовать данные нового кэша, если он доступен. Важно отметить, что даже если имеется новый файл манифеста, приложение будет по-прежнему продолжать использовать старый кэш (как определено в старом файле манифеста), пока не будет вызвана функция swapCache(). Когда вызывается swapCache(), кэш будет использоваться, как определено в новом файле манифеста.

Обычно не требуется использовать функцию update(), так как браузер должен автоматически делать это при перезагрузке страницы. Наиболее часто функцию swapCache() будет использоваться в соединении с событием onupdateready (обновление готово).

В следующем примере, если изменить файл манифеста и перезагрузить страницу, браузер загрузит новые файлы в кэш, и затем переключится на новый кэш (так как вызывается функция swapcache() ):

<html manifest="demo.manifest">
<head>
<script type="text/javascript">
window.applicationCache.addEventListener('updateready', function(){
window.applicationCache.swapCache();
}, false);
</script>
</head>
<body>
...
</body>
</html>

Если созданная страница вряд ли будет перезагружаться пользователем в течение какого-то времени, то можно было бы периодически вызывать функцию update(), чтобы проверять наличие обновлений файла манифеста, и в положительном случае вызывать функцию swapcache() на событии updateready, чтобы загрузить и переключиться на новый кэш:

setInterval(function () { window.applicationCache.update(); }, 3600000); // Проверять обновления файла манифеста каждые 60 минут. Если он обновляется, загрузить новый кэш, как определено новым файлом манифеста.

window.applicationCache.addEventListener('updateready', function(){
// когда обновленный кэш загрузится и будет готов для использования
window.applicationCache.swapCache();
//переключитесь на самую новую версию кэша
}, false);

Этот код будет проверять наличие обновленной версии файла манифеста каждые 60 минут. Если он находит версию файла манифеста на сервере, отличную от встречавшейся ранее, он загрузит новый кэш на основе этого нового манифеста. Когда это произойдет, будет порождаться событие updateready, сообщающее, что обновленная версия кэша закончила загружаться и готова к использованию. Затем можно явно использовать функцию swapCache(), чтобы переключиться со старого кэша на новый, только что загруженный.

Таким образом можно гарантировать, что кэш пользователя будет оставаться обновленным.


--