Руководство для начинающих по использованию кэша приложений

HTML5 Rocks

Введение

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

Использование кэш-интерфейса дает приложению три преимущества:

  1. поиск в режиме офлайн – пользователи могут просматривать весь сайт в режиме офлайн;
  2. скорость – ресурсы кэшируются локально, поэтому быстрее загружаются;
  3. уменьшение нагрузки на сервер – браузер загружает только измененные ресурсы.

Кэш приложений (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, в режиме офлайн.

Обновление кэша

Офлайн-приложение хранится в кэше, пока не произойдет одно из перечисленных ниже событий.

  1. Очистка хранилища данных для соответствующего сайта в браузере.
  2. Изменения в файле манифеста. Обратите внимание: обновление файла, указанного в манифесте, не означает, что браузер повторно кэширует этот ресурс. Для этого должен измениться сам файл манифеста.
  3. Программное обновление кэша приложения.

Статус кэша

Программный доступ к кэшу приложения в браузере обеспечивает объект 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);

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

Ссылки

Comments

0