Как правильно сделать HTML5 Cache Manifest недействительным для онлайн / оффлайн веб-приложений? - PullRequest
53 голосов
/ 11 ноября 2009

В настоящее время я использую манифест кэша (как описано здесь ). Это эффективно делает необходимые ресурсы для запуска приложения доступными, когда пользователь находится в автономном режиме.

К сожалению, это работает слишком хорошо.

После загрузки манифеста кэша Firefox 3.5+ кэширует все ресурсы, явно указанные в манифесте кэша. Однако, если файл на сервере обновляется, и пользователь пытается принудительно обновить страницу, находясь в сети (включая сам кеш-манифест), Firefox полностью откажется от загрузки чего-либо. Приложение остается полностью замороженным на последнем этапе его кэширования. Вопросы:

  1. Я хочу, чтобы Firefox эффективно полагался на кэшированные ресурсы только при сбое сетевого подключения. Я пытался использовать блок FALLBACK, но безрезультатно. Это вообще возможно?
  2. Если # 1 невозможно, то может ли пользователь принудительно обновить страницу и обойти этот кеш (ctrl-F5 этого не делает, и при этом шокирующе не очищает кеш браузера), за исключением очистки своего личного данные? В качестве альтернативы, поддерживает ли механизм манифеста кеша истечение срока действия заголовков и его поведение относительно этого задокументировано где-либо?

Ответы [ 6 ]

25 голосов
/ 11 ноября 2009

Думаю, я понял это: если в манифесте кеша есть ошибка (скажем, ссылочный файл не существует), то Firefox полностью прекратит обработку всего, что связано с applicationCache. Это означает, что он ничего не обновит в вашем кеше, в том числе в манифесте кеша.

Чтобы выяснить, что это была проблема, я позаимствовал некоторый код из 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('<br/>'+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 функцию, которая выводит искаженные манифесты кэша, по крайней мере, на консоль ошибок. Он не должен требовать пользовательский код для присоединения к этим событиям, чтобы диагностировать проблему так же тривиально, как переименованный файл.

15 голосов
/ 21 ноября 2011

Я использовал код из 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);
7 голосов
/ 20 марта 2012

У меня была та же проблема: как только Firefox сохранял автономные файлы, он никогда не перезагружал их. Chrome работал должным образом, он проверял файл манифеста на наличие изменений и перезагружал все, если файл манифеста изменился. Firefox даже не загрузил файл манифеста с сервера, поэтому он не мог заметить изменений.

После расследования я обнаружил, что Firefox кеширует файл манифеста кеша (старомодный кеш, а не автономный кеш). Установка заголовка кэша файла манифеста на Cache-Control: no-cache, private решила проблему.

7 голосов
/ 13 ноября 2009

Отказ от ответственности: мой опыт работы с манифестами и кешем - это все, что Safari и FF могут обрабатывать некоторые вещи по-разному.

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

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

  3. При следующей загрузке сайта, если манифест изменился при предыдущей загрузке, будут загружены новые файлы.

ВСЕГДА НУЖНО ПЕРЕГРУЗИТЬ ДВАЖДЫ, чтобы увидеть какие-либо изменения. На самом деле, мне иногда приходилось перезагружать 3 раза, чтобы увидеть обновление. Понятия не имею, почему.

При отладке я генерирую файл манифеста на лету с помощью php, поэтому в имени файла нет опечатки. Я также генерирую номер версии случайным образом каждый раз для принудительного обновления, но у меня все еще есть автономное веб-приложение для тестирования.

После завершения php-файл может просто отображать сохраненные данные манифеста с постоянным номером версии, и кеш всегда будет использоваться.

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

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

3 голосов
/ 30 сентября 2010

Я сделал дополнение к Firefox, которое делает недействительным Манифест кэша и очищает локальное хранилище 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()
2 голосов
/ 04 июля 2010

Хм, я только что вызвал update () в кеше, после внесения изменений в файл манифеста, получил полную последовательность проверки / загрузки / готовности, сделал одну перезагрузку и текстовое изменение, которое я сделал в одном мои js-файлы, которые отображаются на начальной странице моего приложения, быстро появились.

Кажется, мне нужна только одна перезагрузка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...