Как правильно аннулировать манифест кэша HTML5 для онлайн-приложений или офлайн-приложений?
В настоящее время я использую манифест Cache (как описано здесь). Это эффективно делает необходимые ресурсы для запуска приложения доступным, когда пользователь находится в автономном режиме.
К сожалению, это работает слишком хорошо.
После загрузки манифеста кэша Firefox 3.5+ кэширует все ресурсы, явно указанные в манифесте кэша. Однако, если файл на сервере обновлен, и пользователь пытается обновить страницу во время онлайн (включая сам манифест кэша), Firefox абсолютно откажется извлечь что-либо. Приложение остается полностью замороженным в последней точке, в которой оно было кэшировано. Вопросы:
- Я хочу, чтобы Firefox эффективно использовал только кешированные ресурсы при сбое сетевого подключения. Я пробовал использовать блок FALLBACK, но безрезультатно. Возможно ли это?
- Если # 1 невозможно, возможно ли пользователю принудительно обновить страницу и обойти этот кеш (ctrl-F5 не делает этого и не очищает кеш браузера, в шоке), не освобождая их частные данные? В качестве альтернативы, механизм кэширования-манифеста поддерживает заголовки истечения срока действия и является ли его поведение в отношении этого документально зарегистрированным где угодно?
Ответы
Ответ 1
Я думаю, что это выяснилось: если в одном проявлении кеша есть ошибка (скажем, файл с ссылками не существует), то Firefox полностью прекратит обработку любого связанного приложения. Значит, он ничего не обновит в вашем кеше, в том числе ваш кеш-манифест.
Чтобы узнать, что это была проблема, я заимствовал некоторый код из Mozilla и упал в новый (не кэшированный) HTML файл в мое выражение. Заключительное сообщение, записанное в журнале, показало, что может быть проблема в моем манифесте кэш-памяти, и, конечно же, был (отсутствующий файл).
// Convenience array of status values
var cacheStatusValues = [];
cacheStatusValues[0] = 'uncached';
cacheStatusValues[1] = 'idle';
cacheStatusValues[2] = 'checking';
cacheStatusValues[3] = 'downloading';
cacheStatusValues[4] = 'updateready';
cacheStatusValues[5] = 'obsolete';
// Listeners for all possible events
var cache = window.applicationCache;
cache.addEventListener('cached', logEvent, false);
cache.addEventListener('checking', logEvent, false);
cache.addEventListener('downloading', logEvent, false);
cache.addEventListener('error', logEvent, false);
cache.addEventListener('noupdate', logEvent, false);
cache.addEventListener('obsolete', logEvent, false);
cache.addEventListener('progress', logEvent, false);
cache.addEventListener('updateready', logEvent, false);
// Log every event to the console
function logEvent(e) {
var online, status, type, message;
online = (isOnline()) ? 'yes' : 'no';
status = cacheStatusValues[cache.status];
type = e.type;
message = 'online: ' + online;
message+= ', event: ' + type;
message+= ', status: ' + status;
if (type == 'error' && navigator.onLine) {
message+= ' There was an unknown error, check your Cache Manifest.';
}
log('
'+message);
}
function log(s) {
alert(s);
}
function isOnline() {
return navigator.onLine;
}
if (!$('html').attr('manifest')) {
log('No Cache Manifest listed on the tag.')
}
// Swap in newly download files when update is ready
cache.addEventListener('updateready', function(e){
// Don't perform "swap" if this is the first cache
if (cacheStatusValues[cache.status] != 'idle') {
cache.swapCache();
log('Swapped/updated the Cache Manifest.');
}
}
, false);
// These two functions check for updates to the manifest file
function checkForUpdates(){
cache.update();
}
function autoCheckForUpdates(){
setInterval(function(){cache.update()}, 10000);
}
return {
isOnline: isOnline,
checkForUpdates: checkForUpdates,
autoCheckForUpdates: autoCheckForUpdates
}
Это, безусловно, было полезно, но я должен обязательно запросить функцию Mozilla, которая выводит из строя искаженные кэш-манифеста, по крайней мере, на консоль ошибок. Он не должен требовать, чтобы специальный код добавлялся к этим событиям, чтобы диагностировать проблему как тривиальную, как переименованный файл.
Ответ 2
Я использовал код из HTML5 Rocks: обновил кеш:
window.addEventListener('load', function(e) {
if (window.applicationCache) {
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);
Ответ 3
Отказ от ответственности: мой опыт работы с манифестами и кешем - все Safari и FF могут обрабатывать некоторые вещи по-разному.
-
Вы совершенно правы. Если в манифесте есть файлы, которые не могут быть найдены, кэширование не произойдет.
-
Даже если вы в сети, браузер проверяет только файл манифеста. Ожидая файл манифеста, он будет продолжать загружать сайт из кеша - таким образом, он не задерживает рендеринг, но это означает, что вы не видите никаких изменений при первом загрузке.
-
В следующий раз, когда сайт будет загружен, если манифест изменился при предыдущем загрузке, будут загружены новые файлы.
ВСЕГДА НЕОБХОДИМО ПЕРЕЕЗДАТЬ ДВАЖДЫ, чтобы увидеть какие-либо изменения. На самом деле мне иногда приходилось перезагружать 3 раза, чтобы увидеть обновление. Не знаю, почему.
При отладке я создаю файл манифеста "на лету" с помощью php, поэтому нет возможности опечатки в имени файла. Я также произвольно генерирую номер версии каждый раз, чтобы принудительно обновить, но все еще имею автономный webapp для тестирования.
После завершения, php файл может просто эхо сохранить сохраненные данные манифеста с постоянным номером версии, и кеш всегда будет использоваться.
Только некоторые вещи, которые я узнал, играя с манифестом и кешем в последнее время. Он отлично работает, но может быть запутанным.
Нет истечения срока действия. Чтобы избавиться от необходимости, вы должны изменить файл манифеста, чтобы ничего не иметь и перезагрузить. В Safari очистка кеша пользователя очищает все кэшированные файлы.
Ответ 4
У меня была такая же проблема: однажды Firefox сохранил автономные файлы, это не перезагрузило бы их когда-либо. Chrome работал должным образом, он проверял файл манифеста на изменения и перезагружал все, если файл манифеста изменился. Firefox даже не загружал файл манифеста с сервера, поэтому он не заметил изменений.
После исследования я узнал, что Firefox кэширует файл манифеста кэша (старомодный кеш, а не автономный кеш). Настройка заголовка кэша файла манифеста на Cache-Control: no-cache, private
решила проблему.
Ответ 5
Я сделал надстройку Firefox, которая делает недействительным манифест Cache и очищает локальное хранилище HTML5.
http://sites.google.com/site/keigoattic/home/webrelated#TOC-Firefox-HTML5-Offline-Cache-and-Loc
Вы также можете аннулировать манифест кэша, введя код ниже в консоли ошибок:
// invalidates the cache manifest
var mani = "http://.../mysite.manifest"; // manifest URL
Components.classes["@mozilla.org/network/application-cache-service;1"].getService(Components.interfaces.nsIApplicationCacheService).getActiveCache(mani).discard();
Или, набрав код, указанный ниже в адресной строке, вручную измените кеш, который нужно обновить:
javascript:applicationCache.update()
Ответ 6
Хм, я только что вызвал update() в кеше, после внесения изменений в файл манифеста и получил полную последовательность проверки/загрузки/готовности, перезагрузки и изменения текста, которые я сделал в одном из моих js файлов, которые появляются на начальной странице моего приложения, быстро появились.
Кажется, мне нужна только перезагрузка.