- PVSM.RU - https://www.pvsm.ru -
Постепенно концепция стандарта HTML5 становиться реальностью. Браузеры начинают поддерживать новые возможности, которых так не хватало. Но с новыми возможностями появляются и новые проблемы.
В данной статье рассматривается Application Cache API — совокупность функций, обеспечивающих продвинутое кэширование ресурсов web-приложения, и с помощью которых можно просматривать загруженные ранее сайты без подключения к сети Интернет. Особое внимание я уделил практическому использованию и проблемам Application Cache.
Далее по статье под словами «кэш» и его производными имеется в виду Application Cache и работа с ним. Стандартный кэш браузера обозначается как «стандартный кэш».
Механизм работы Application Cache на первый взгляд прост. Когда пользователь первый раз пользуется сайтом, страницы запоминаются в кэше браузера. Затем при последующих посещениях, а также когда соединение с Интернет теряется, используются заранее сохраненные данные в специальном «хранилище». Контроль над кэшированием сайта производится с помощью специального файла, названного manifest. В некоторых статьях используется .apppcache вместо .manifest. В данной статье используется .manifest. Хотя можно использовать и свое название.
«Хранилище» — условное название, используемое в браузерах для обозначения места хранения Application Cache. Механизмы работы Application Cache и стандартного кэша браузера различны, поэтому требуют отдельного размещения. Отличия механизмов работы между двумя видами кэширования следующие:
Данные различия оказывают существенное влияние на механизмы кэширования, которые будут подробно рассмотрены в конце статьи.
Первоначально необходимо «включить» Application Cache. Это делается путём указания браузеру на файл .manifest с помощью атрибута manifest в теге html:
<!DOCTYPE html>
<html manifest="cache.manifest">
Здесь существуют две особенности:
После этого достаточно только предоставить пользователю первый файл .manifest, но и тут нас ожидает два важных момента:
AddType text/cache-manifest .manifest
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/cache-manifest "access plus 0 seconds"
</IfModule>
Проделав эти операции, мы можем заняться содержимым файла .manifest.
Приведём пример такого файла:
CACHE MANIFEST
# Версия 1
images/logo.png
CACHE:
css/default.css
NETWORK:
index.php
FALLBACK:
/ /offline.html
Первая строчка содержит текст CACHE MANIFEST — она означает, что данный файл является файлом manifest. Она обязательна.
Комментарии в файле обозначаются с помощью символа решетки #.
Пустые строки или строки с пробелами игнорируются и используются только для логического разделения.
В примере за комментарием следует, так называемое, «явное вхождение» (images/logo.png) – аналог раздела CACHE. Может использоваться, как и совместно с этим разделом, так и замещая его.
Каждое правило (ресурс) должно быть прописано на отдельной строке.
Далее следуют три раздела. Название разделов, как и текст CACHE MANIFEST, должны быть в верхнем регистре. Каждый раздел выполняет свои функции. Порядок следования разделов не важен. Должен быть хотя бы один раздел. Разделы могут быть пустыми.
Давайте разберем каждый раздел.
Этот раздел является разделом по умолчанию, т.е. если в файле .manifest нет никаких заголовков («явное вхождение»), то содержание этого файла принимается за содержание раздела CACHE. Внутри этого раздела размещаются пути или URI к кэшируемым ресурсам. Существуют следующие особенности:
В этом разделе размещаются пути к файлам, которые обязательно должны загружаться из интернета. В этом разделе можно использовать паттерны, т.е. можно написать такую конструкцию:
CACHE MANIFEST
NETWORK:
*
Это разрешит загрузку всех файлов, которые не имеют сохраненной копии. Если требуются какие-то ограничения на загрузку, то можно указывать конкретные файлы (например, index.php) и директории (например, /images/*).
В этом разделе указывается, что браузеру в offline-режиме отображать при обращении к страницам, которые не были кэшированы. Запись правил осуществляется по следующему принципу:
запрашиваемая_страница отображаемая_страница
Разделять пути можно и пробелами и табуляцией.
Относительно этого раздела существую следующие особенности:
CACHE MANIFEST
FALLBACK:
/ /offline.html
Можно использовать указания на конкретные файлы или файлы с определённым расширением (например, *.html /offline.html), что очень удобно.
Существует три замечания, которые нельзя опустить:
При объявлении атрибута manifest у нас появляется возможность работать с объектом управления кэшем для данного документа window.applicationCache. Совокупность функций и методов работы с этим объектом и образуют Application Cache API.
Рассмотрим этот объект подробно.
Обращение к объекту выглядит следующим образом:
window.applicationCache
Теперь сами методы.
window.applicationCache.status
Метод возвращает числовое значение соответствующее статусу состояния кэша. Возможны следующие статусы:
Так же в объекте applicationCache определены константы состояния (например, cache.IDLE равно 1). Так что числовые значения необязательно запоминать.
window.applicationCache.update()
Метод инициирует процесс проверки файла .manifest и последующие скачивание необходимых ресурсов.
window.applicationCache.swapCache()
Метод переключает браузер на использование новых кэшированных файлов вместо старых. Перерисовки страницы не происходит, только при последующем обращении к кэшированным файлам они берутся уже из обновлённого кэша.
Простой альтернативой метода является перезагрузка страницы, например, при помощи location.reload().
С объектом applicationCache связанны следующие события:
Всё вроде бы хорошо и складно, но как это работает в реальности? Сейчас мы с Вами разберёмся с этим вопросом.
Первое, что следует рассмотреть, это дельная пошаговая схема работы Application Cache:
Отдельно необходимо рассмотреть вопрос об обновлении (очистке) кэша. Из анализа детализированной схемы работы Application Cache видно, что изменение на сервере данных не приводит к автоматическому обновлению этих данных в кэше. Обновление кэша можно произвести следующими способами:
CACHE MANIFEST
# Версия 2
Для использования в реальных проектах подходят лишь последние два способа, которые были бы достаточно удобны, если бы не «агрессивное кэширование» браузера Mozilla Firefox.
Браузер Mozilla Firefox имеет «своеобразный» механизм обновления кэша, известный как «агрессивное кэширование». Проблема проявляется, когда мы совмещаем стандартное кэширование и Application Cache, а нам их совмещать необходимо, если мы хотим иметь кэширование в старых браузерах.
Дело в том, что при обновлении Application Cache в Mozilla Firefox данные также берутся из стандартного кэша без проверки изменений на сервере. Это приводит к тому, что в обновлённый Application Cache могут попасть устаревшие данные из стандартного кэша, т.е. обновление будет выполнено, но в кэше будит старые версии файлов. Данный факт ставит все преимущества работы с Application Cache под сомнение.
Корректными способами обновления кэша в такой ситуации являются:
В первом случаи мы просто меняем имя измененного файла во всех ресурсах, где он упоминается, в том числе и файле .manifest. Файла с первоначальным именем существовать не должно(!). В результате при очередной проверке изменения произойдёт ошибка загрузки несуществующего файла, и ресурсы кэша будут загружены с сервера.
Если вариант с изменением имени файла не подходит в силу тех или иных причин, то необходимо воспользоваться 2-хступенчитым обновлением кэша.
На первом этапе обновления мы исключаем изменённый файл из раздела CACHE файла .manifest и устанавливаем в заголовке отдаваемого файла старевший срок годности:
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
В результате у активных пользователей данный файл обновиться в стандартном кэше, а из Application Cache будет удалён.
На втором этапе мы уже включаем измененный файл в раздел CACHE, и он успешно кэшируется. К сожалению, данное обновление коснется только активных пользователей, поэтому старайтесь использовать переименование файлов.
Ещё один важный момент, о котором нужно упомянуть – кэш привязан к домену, а не к странице, где объявлен файл .manifest. Сохранённые в кэше, ресурсы будут использоваться для всех страниц данного домена, даже если в них нет ссылки на файл .manifest. Это достаточно удобно – можно на стартовой странице определить кэшируемые ресурсы, а потом не беспокоится об их кэшировании на других страницах.
Если же мы используем несколько разных файлов .manifest для разных страниц одного домена, то они будут перекрывать друг друга. В кэше будут храниться только те ресурсы, которые были указанны в последнем загруженном файле .manifest.
Также при использовании нескольких файлов .manifest можно создать ситуацию, когда сохраняемые страницы циклически кэшируют друг друга. Возникновение такой ситуации приводит приложение в не рабочие состояние. Учитывая, выше написанное, следует отметить, что использовать несколько файлов .manifest непрактично и рискованно, хотя такая возможность существует.
Из привязки к домену также следует, что Application Cache работает во фреймах, используя кэш домена фрейма. Этот момент по достоинству должны оценить разработчики игр.
Ещё одним несомненным преимуществом Application Cache является возможность работы в режиме offline. Только представьте себе – у клиента временно перестала работать сеть, но он всё равно может осуществлять работу с вашим ресурсом.
Но даже здесь не всё гладко. Вспомним одну особенность Application Cache – страница, на которой объявлен файл .manifest всегда попадает в кэш. В результате получается, что страница будет загружена, руководствуясь разделом CACHE, а не FALLBACK. То есть приложение будет вести себя, так как будто связь есть. Но как определить, что соединение отсутствует?
Для этого в спецификации HTML5 определенны два события online и offline, которые вызываются при создании и разрыве соединения соответственно. Но пока они ни в одном из браузеров не работают. Также можно воспользоваться свойством online объекта navigator:
window.navigator.onLine
Это свойство возвращает true при наличии соединение и false при его отсутствии. Получается, что при инициализации страницы нужно проверять это свойство и далее строить работу на основе его значения. На данный момент времени свойство navigator.onLine поддерживают браузеры Mozilla Firefox 2, Internet Explorer 4 и старше.
Пример использования:
<!DOCTYPE HTML>
<html lang="ru" manifest="cache.manifest">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Application Cache Test</title>
</head>
<body>
<style>
html {font-family: "DejaVu Sans", "Geneva CY", "Verdana"; background: #FFFFFF; OVERFLOW: hidden; ; border: 0;}
body {width: 880px; height: 600px; position: relative; background: #999999; margin: 20px auto; box-shadow: 0 0 15px 10px #999999; -webkit-box-shadow: 0 0 15px 10px #999999; -moz-box-shadow: 0 0 15px 10px #999999;}
/* Экран загрузки*/
.progressbar {display:none; position:absolute; left:0px; top:0px; width:880px; height:600px; background-color:#333333; z-index:256; border:1px solid #333333;}
.progressbar #progresstext {position:absolute; left:0px; top:200px; width:880px; color:#66FF00; text-align:center; font-size:36px; text-shadow:0 0 0.8em #AAFF00, 0 0 0.8em #AAFF00;}
.progressbar #progress {position:absolute; left:100px; top:300px; width:600px; height:40px;}
/* Заставка */
.flash {position:absolute; left:0px; top:0px; width: 880px; height: 600px; background-color:#666666; z-index:51; border: 1px solid #333333;}
</style>
<!-- Блокирующее окно -->
<div id="flash" class="flash"></div>
<!-- Окно загрузки -->
<div id="progressbar" class="progressbar"><div id="progresstext">Загрузка</div><progress id="progress"></progress></div>
<script type="text/javascript" src="js/jquery-1.5.min.js"></script>
<script type="text/javascript">
// Переменные прогресса
var progress_value = 0;
var progress_max = 1;
$(function() {
// Проверяем подключение
if (navigator.onLine) {
alert('Соединение есть');
}
else {
alert('Невозможно установить соединение с сервером');
}
// Получаем объект Application Cache
cache = window.applicationCache;
if (cache) {
// Добавляем слушателей событий
// Ресурсы уже кэшированнны. Индикатор прогресса скрыт.
cache.addEventListener('cached', function(e) {ProgressHide();}, false);
// Начало скачивания ресурсов. progress_max - количество ресурсов. Показываем индикатор прогресса
cache.addEventListener('downloading', function(e) {ProgressShow(); progress_max = 3;}, false);
// Процесс скачивания ресурсов. Индикатор прогресса изменяется
cache.addEventListener('progress', function(e) {ProgressChange();}, false);
// Скачивание ресурсов. Скрываем индикатор прогресса. Обновляем кэш. Перезагружаем страницу.
cache.addEventListener('updateready', function(e) {ProgressHide(); window.applicationCache.swapCache(); location.reload();}, false);
}
});
// Отслеживаем нажатие клавиш клавиатуры
$(document).keyup(function(event){
// При нажатии shift+1 производиться попытка обновления кэша
if (event.shiftKey && event.keyCode == 49) {
window.applicationCache.update();
}
return false;
});
//------------------- Функции управлением экраном загрузки ----------------//
function ProgressShow() {
$("#progressbar").show(300);
progress_value = 0;
}
function ProgressChange() {
progress_value++;
$("#progress").attr({max: progress_max, value: progress_value});
}
function ProgressHide() {
$("#progressbar").hide(300);
}
//-------------------------------------------------------------------------//
</script>
</body>
</html>
Описанной выше информации достаточно, что бы понять как работает Application Cache. Можно сделать первые выводы о возможностях и трудностях.
К возможностям и преимуществам Application Cache относятся:
К проблемам использования Application Cache относятся:
Так же следует обратить внимание на следующие нюансы:
Несмотря на целую кучу проблем использования, Application Cache — это мощный механизм оптимизации для нагруженных систем. Особенно он будет полезен для игр и интерактивных приложений, использующих FullAjax. Правильное использование Application Cache позволит не только увеличить скорость загрузки страниц пользователям и уменьшить количество трафика, но и снизить нагрузку на Ваш сервер, т.к. кэшированные страницы загружаются не с сервера, а с локального хранилища.
Надеюсь, что эта статья позволит Вам открыть для себя всю мощь Application Cache.
Автор: VitaZheltyakov
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/15468
Ссылки в тексте:
[1] support.mozilla.com/ru/kb/okno-nastrojki-panel-dopolnitelnye#w_ahaalaklai-eaulikioi: http://support.mozilla.com/ru/kb/okno-nastrojki-panel-dopolnitelnye#w_ahaalaklai-eaulikioi
[2] help.opera.com/Windows/11.50/ru/storage.html: http://help.opera.com/Windows/11.50/ru/storage.html
Нажмите здесь для печати.