Введение
Все более важным для веб-приложений становится доступ в режиме офлайн. Механизмы кэширования есть в каждом браузере, но они ненадежны и не всегда работают так, как хотелось бы. HTML5 решает некоторые задачи автономной работы с помощью интерфейса ApplicationCache.
Использование кэш-интерфейса дает приложению три преимущества:
- поиск в режиме офлайн – пользователи могут просматривать весь сайт в режиме офлайн;
- скорость – ресурсы кэшируются локально, поэтому быстрее загружаются;
- уменьшение нагрузки на сервер – браузер загружает только измененные ресурсы.
Кэш приложений (AppCache) позволяет разработчику указать, какие файлы браузер должен кэшировать и сделать доступными для автономных пользователей. Приложение будет загружаться и работать корректно, даже если пользователь обновит страницу без подключения к Интернету.
Файл манифеста кэша
Файл манифеста кэша представляет собой простой текстовый файл со списком ресурсов, которые браузер должен кэшировать для доступа в автономном режиме.
Обращение к файлу манифеста
Чтобы разрешить кэширование приложения, включите атрибут manifest в тег html документа:
<html manifest="example.appcache"> ... </html>
Атрибут manifest должен присутствовать на каждой странице веб-приложения, которое нужно кэшировать. Браузер не кэширует страницу, если она не содержит атрибут manifest или не указана в самом файле манифеста. Это означает, что любая страница с атрибутом manifest, которую посетит пользователь, будет неявным образом добавлена в кэш приложения. Таким образом, перечислять в манифесте все страницы не нужно.
Атрибут manifest может указывать на абсолютный URL или относительный путь, но абсолютный URL должен находиться в том же домене, что и веб-приложение. Файл манифеста может иметь любое расширение, но его MIME-тип должен быть правильным (см. ниже).
<html manifest="http://www.example.com/example.mf"> ... </html>
В качестве MIME-типа для файла манифеста необходимо указывать значение text/cache-manifest. Возможно, в конфигурацию веб-сервера или файл .htaccess придется добавить пользовательский тип файла.
Например, чтобы настроить этот MIME-тип в Apache, добавьте в файл конфигурации следующую строку:
AddType text/cache-manifest .appcache
А для файла app.yaml в Google App Engine код будет выглядеть так:
- url: /mystaticdir/(.*\.appcache) static_files: mystaticdir/\1 mime_type: text/cache-manifest upload: mystaticdir/(.*\.appcache)
Структура файла манифеста
Простой файл манифеста может выглядеть примерно так:
CACHE MANIFEST index.html stylesheet.css images/logo.png scripts/main.js
В этом примере кэшируются четыре файла на странице, которая указывает на данный файл манифеста.
Необходимо отметить несколько моментов.
- Строка
CACHE MANIFESTявляется обязательной и должна быть первой. - Объем кэшированных данных для сайтов не может превышать 5 МБ. При написании приложений для Интернет-магазина Chrome это ограничение можно снять с помощью атрибута
unlimitedStorage. - Если файл манифеста или указанный в нем ресурс загрузить не удается, кэш не обновляется. В этом случае браузер продолжает использовать старый кэш приложения.
Рассмотрим более сложный пример.
CACHE MANIFEST # 2010-06-18:v2 # Explicitly cached 'master entries'. CACHE: /favicon.ico index.html stylesheet.css images/logo.png scripts/main.js # Resources that require the user to be online. NETWORK: login.php /myapi http://api.twitter.com # static.html will be served if main.py is inaccessible # offline.jpg will be served in place of all images in images/large/ # offline.html will be served in place of all other .html files FALLBACK: /main.py /static.html images/large/ images/offline.jpg *.html /offline.html
Строки, которые начинаются с символа #, являются комментариями, но могут служить и для другой цели. Кэш приложения обновляется только при изменении файла манифеста. Это означает, что, например, изменения, внесенные в графический ресурс или функцию JavaScript, повторно не кэшируются. Для обновления кэшированных файлов необходимо отредактировать сам файл манифеста. Чтобы у пользователей всегда была последняя версия приложения, можно создать строку комментария с номером версии, хэш-суммой файлов или датой. С появлением новой версии кэша можно обновлять и программными средствами, как описано в разделе Обновление кэша.
Манифест может содержать три раздела: CACHE, NETWORK и FALLBACK.
CACHE- Это раздел для записей по умолчанию. Файлы, указанные здесь (или сразу после атрибута
CACHE MANIFEST), будут кэшироваться при первой же загрузке. NETWORK- Файлы, указанные в этом разделе, представляют собой надежные ресурсы, которым необходимо подключение к серверу. Все запросы к ним идут в обход кэша, даже если пользователь находится в режиме офлайн. Здесь можно использовать знаки подстановки.
FALLBACK- Дополнительный раздел, содержащий резервные страницы на случай, если ресурс недоступен. Первый URL указывает ресурс, а второй – его резервную страницу. Оба адреса должны быть относительными и находиться в том же домене, что и файл манифеста. Здесь можно использовать знаки подстановки.
Примечание. Разделы могут быть указаны в любом порядке, и каждый из них может встречаться в одном манифесте несколько раз.
Следующий манифест определяет "универсальные" страницы (offline.html), которые будут отображаться, если пользователь пытается получить доступ к корневому каталогу сайта в автономном режиме. Он также указывает на то, что все остальные ресурсы (например, на удаленном сайте) требуют подключения к Интернету.
CACHE MANIFEST # 2010-06-18:v3 # Explicitly cached entries index.html css/style.css # offline.html will be displayed if the user is offline FALLBACK: / /offline.html # All other resources (e.g. sites) require the user to be online. NETWORK: * # Additional resources to cache CACHE: images/logo1.png images/logo2.png images/logo3.png
Примечание. HTML-файл, который ссылается на ваш файл манифеста, кэшируется автоматически. Указывать его в манифесте необязательно, но рекомендуется.
Примечание. Манифесты кэша заменяют собой заголовки HTML-кэша и ограничения на кэширование страниц, обслуживаемых через SSL. Это гарантирует доступ к страницам, которые обслуживаются по протоколу HTTPS, в режиме офлайн.
Обновление кэша
Офлайн-приложение хранится в кэше, пока не произойдет одно из перечисленных ниже событий.
- Очистка хранилища данных для соответствующего сайта в браузере.
- Изменения в файле манифеста. Обратите внимание: обновление файла, указанного в манифесте, не означает, что браузер повторно кэширует этот ресурс. Для этого должен измениться сам файл манифеста.
- Программное обновление кэша приложения.
Статус кэша
Программный доступ к кэшу приложения в браузере обеспечивает объект window.applicationCache. Его свойство status позволяет проверить текущее состояние кэша:
var appCache = window.applicationCache;
switch (appCache.status) {
case appCache.UNCACHED: // UNCACHED == 0
return 'UNCACHED';
break;
case appCache.IDLE: // IDLE == 1
return 'IDLE';
break;
case appCache.CHECKING: // CHECKING == 2
return 'CHECKING';
break;
case appCache.DOWNLOADING: // DOWNLOADING == 3
return 'DOWNLOADING';
break;
case appCache.UPDATEREADY: // UPDATEREADY == 4
return 'UPDATEREADY';
break;
case appCache.OBSOLETE: // OBSOLETE == 5
return 'OBSOLETE';
break;
default:
return 'UKNOWN CACHE STATUS';
break;
};
Чтобы обновить кэш программным образом, нужно прежде всего вызвать функцию applicationCache.update(). Она попытается обновить кэш пользователя (для этого необходимо, чтобы файл манифеста изменился). После того как атрибут applicationCache.status перейдет в состояние UPDATEREADY, функция applicationCache.swapCache() заменит старый кэш на новый.
var appCache = window.applicationCache;
appCache.update(); // Attempt to update the user's cache.
...
if (appCache.status == window.applicationCache.UPDATEREADY) {
appCache.swapCache(); // The fetch was successful, swap in the new cache.
}
Примечание. В результате подобного вызова функций update() и swapCache() клиенту не отправляются обновленные ресурсы. Эта последовательность просто указывает браузеру, что нужно проверить новый манифест, загрузить указанное обновленное содержание и повторно заполнить кэш приложения. В результате страница скачивается с сервера дважды: в первый раз заполняется новый кэш приложения, а во второй – обновляется содержание страницы.
Однако двойной загрузки можно избежать. Чтобы отправлять пользователям новую версию сайта, настройте отслеживание события updateready при загрузке страницы:
// Check if a new cache is available on page load.
window.addEventListener('load', function(e) {
window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
// Browser downloaded a new app cache.
// Swap it in and reload the page to get the new hotness.
window.applicationCache.swapCache();
if (confirm('A new version of this site is available. Load it?')) {
window.location.reload();
}
} else {
// Manifest didn't changed. Nothing new to server.
}
}, false);
}, false);
События AppCache
Как можно предположить, для контроля за состоянием кэша используются дополнительные события. Браузер инициирует их во время загрузки, при обновлении кэша приложения и возникновении ошибки. Приведенный ниже фрагмент задает прослушиватели для каждого типа событий кэша.
function handleCacheEvent(e) {
//...
}
function handleCacheError(e) {
alert('Error: Cache failed to update!');
};
// Fired after the first cache of the manifest.
appCache.addEventListener('cached', handleCacheEvent, false);
// Checking for an update. Always the first event fired in the sequence.
appCache.addEventListener('checking', handleCacheEvent, false);
// An update was found. The browser is fetching resources.
appCache.addEventListener('downloading', handleCacheEvent, false);
// The manifest returns 404 or 410, the download failed,
// or the manifest changed while the download was in progress.
appCache.addEventListener('error', handleCacheError, false);
// Fired after the first download of the manifest.
appCache.addEventListener('noupdate', handleCacheEvent, false);
// Fired if the manifest file returns a 404 or 410.
// This results in the application cache being deleted.
appCache.addEventListener('obsolete', handleCacheEvent, false);
// Fired for each resource listed in the manifest as it is being fetched.
appCache.addEventListener('progress', handleCacheEvent, false);
// Fired when the manifest resources have been newly redownloaded.
appCache.addEventListener('updateready', handleCacheEvent, false);
Если файл манифеста или указанный в нем ресурс загрузить не удается, обновление не выполняется. В этом случае браузер продолжает использовать старый кэш приложения.
Ссылки
- Спецификация API ApplicationCache