Кратко

  • AppCache обещал открывать веб-приложение даже без сети. Страница указывала на манифест с перечнем файлов, и браузер сохранял их. Замена скрипта или картинки на сервере сама по себе не обновляла сохранённый комплект: требовалось изменить манифест.
  • Если манифест или один обязательный файл не загружался, обновление целиком могло сорваться, а старая версия продолжала работать. Chrome начал отключать AppCache по умолчанию в 2020 году. Маленький список ресурсов стал переключателем релизов.

Исправление уже есть, но читатель его не видит

Разработчик исправляет main.js и выкладывает новый файл. Пользователь открывает приложение — прежняя ошибка остаётся. Руководство Google по AppCache описывало причину. Изменение уже сохранённого браузером скрипта или изображения на сервере не заставляло браузер заново сохранить ресурс. Нужно было изменить сам манифест. Новая отметка версии в строке комментария могла стать тем действием, которое действительно выпускало исправление.

Такой порядок делал приложение доступным при пропавшей связи. Одновременно он ставил дополнительную дверь между сервером и экраном. Самый свежий файл ещё не означал самую свежую версию у читателя. Небольшой текстовый список управлял тем, когда браузер начнёт собирать новый комплект.

Сохранить приложение целиком, а не надеяться на случай

Записка W3C от мая 2008 года объясняла замысел через обычную работу: почта, календарь и документы должны открываться после выхода из сети. Обычный HTTP-кеш мог не оставить все нужные части. Атрибут manifest элемента html указывал на файл типа text/cache-manifest; в нём автор перечислял то, что следовало сохранить. Раздел NETWORK: отмечал запросы, которым по-прежнему требовалась сеть.

Явный список обещал больше предсказуемости, чем набор случайно уцелевших ресурсов. Но и новая версия стала собираться как целое. По описанию Google, неудачная загрузка самого манифеста или любого указанного обязательного файла срывала обновление целиком. Браузер продолжал пользоваться старым кешем приложения. Даже полностью скачанный новый комплект не появлялся в уже открытой странице немедленно: страницу нужно было перезагрузить.

Логика берегла пользователя от приложения, собранного наполовину. Она же давала два способа застрять на ошибке. Исправить main.js и забыть о манифесте — браузер сохранит старый скрипт. Изменить манифест, но не отдать один требуемый ресурс — браузер сохранит старую версию снова. «Файл размещён» и «исправление видно» стали разными событиями.

Слишком тихий список и слишком шумный список

Манифест, который не меняется, не зовёт браузер за новыми файлами. Но механическое обновление временной метки при каждом запросе тоже могло мешать. Руководство Google отмечало, что браузер проверял манифест в начале и после скачивания ресурсов. Если за это время список изменился, собранные файлы могли относиться к разным ревизиям. Браузер отклонял такую смесь и пробовал позднее.

Разделы CACHE, NETWORK и FALLBACK определяли, что хранить, что запрашивать из сети и что показывать вместо недоступной страницы. Несколько строк текста становились политикой работы приложения. Отсутствующий обязательный файл мог остановить не только один адрес, но и всю новую сборку.

Браузер предпочитал полный старый комплект неполному новому. Для автономной работы это было осмысленно. Для срочной починки — ещё одна проверка, которую нельзя свести к отметке времени на сервере. Нужна была видимая версия в браузере пользователя.

Chrome назначил выход из старого механизма

Инструкция Chrome 2020 года описала поэтапное прекращение поддержки. Chrome 85 выключал AppCache по умолчанию, а временная origin trial давала сайтам срок на переезд. Для автономной работы предлагались Service Workers. При переходе действовало жёсткое правило: когда Service Worker управлял страницей в Chrome, AppCache на ней больше не работал. Нельзя было настроить новую схему наполовину и рассчитывать, что старая закроет остальные запросы.

Разработчикам приходилось заново определять обработку запросов, набор сохраняемых файлов и способ показать обновление уже открытой вкладке. Инструмент миграции Google воспроизводил часть поведения AppCache, но не заменял интерфейс window.applicationCache и его события. График Chrome был конкретным графиком одного браузера; остальные движки принимали собственные решения.

AppCache сохранял приложение, когда сеть исчезала. После возвращения сети он мог сохранять старую версию и тогда, когда на сервере уже лежало исправление. Список ресурсов стоял между двумя нужными вещами: продолжением работы и своевременной заменой сломанного кода.