API кэш‑хранилища для офлайн‑веб‑приложений
Модель API кэш‑хранилища для офлайн‑приложения: запросы, версии выпусков, резервный ответ и управляемое удаление.
Нужна структурированная документация по теме Идентичность?
Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.
API кэш‑хранилища даёт офлайн‑веб‑приложению именованное хранилище объектов Request и Response. Воркер может открыть кэш, найти запрос и вернуть сохранённый ответ, когда сеть недоступна. API не решает, какие ресурсы можно хранить, когда они считаются свежими и какой аккаунт может их читать: это ответственность приложения.
Поэтому офлайн‑режим является и задачей хранения, и задачей воркера. Надёжная схема именует каждый кэш, меняет его версию при выпуске новых ресурсов, выбирает резервный результат для каждого класса запросов и предоставляет понятный способ удаления. Спецификация воркеров описывает жизненный цикл, а справочник Cache на MDN описывает методы и правила сопоставления.
Что принадлежит кэш‑хранилищу
caches, объект CacheStorage, доступен воркеру и, когда это разрешено, странице. caches.open('app-shell-v3') создаёт или открывает Cache; cache.put(request, response) сохраняет ответ; cache.match(request) ищет запись; caches.delete('app-shell-v2') удаляет именованный кэш целиком. Браузер связывает эти данные с источником и соответствующим профилем или контекстом. Имя кэша является пространством имён приложения, а не границей безопасности между кодом одного источника.
API хранит веб‑объекты: HTML, JavaScript, CSS, изображения и JSON, а также заголовки, влияющие на интерпретацию тела. Сохраняйте только ответы с понятными назначением, сроком и владельцем. Ответ с токеном сессии, данными аккаунта или краткосрочным решением авторизации следует считать состоянием приложения, а не обычным офлайн‑ресурсом.
Кэш‑хранилище отделено от HTTP‑кэша, cookie, localStorage, IndexedDB и регистраций воркеров. Очистка одного хранилища не очищает остальные. При проверке выхода из аккаунта перечислите все используемые хранилища и проверьте каждое. Успешный cache.delete() подтверждает исчезновение одного именованного кэша, но не удаление cookie или записи IndexedDB. См. модель хранилищ браузера и разделение хранилищ, чтобы различать эти границы.
Браузер может удалить данные из‑за нехватки места, а пользователь может очистить их в настройках. Такое удаление является запасной политикой пространства, а не процессом выпуска или гарантией приватности. Приложение должно уметь снова получить нужный ответ при пустом кэше. Если несколько функций используют один источник, задайте отдельные префиксы и удаляйте только имена своей функции.
Сопоставление запросов без неожиданностей
Cache.match() сравнивает запрос с сохранёнными записями по правилам платформы. Это не общий поиск по телу ответа и не разрешение повторять любой HTTP‑метод. Разделите запросы на классы, чтобы политика worker оставалась читаемой.
Статические ресурсы с версией, например пакет JavaScript, подходят для cache-first: сначала проверяется версионированный кэш, а при отсутствии записи ресурс загружается и сохраняется. Для навигации или данных, которые должны отражать состояние сервера, чаще подходит network-first: сначала сеть, затем обновление только проверенным ответом, а сохранённый ответ используется при сбое сети.
Не сохраняйте каждый успешный ответ автоматически. POST, создающий заказ или меняющий профиль, не становится безопасным для повторения из‑за записи ответа в кэш‑хранилище. Ответ, зависящий от заголовка авторизации, cookie или аккаунта, требует явной политики. Во многих случаях безопаснее показать понятный статус недоступности и попросить подключиться снова.
Параметры, заголовки, метод и режим кэша могут менять результат сопоставления. Если представление зависит от заголовка, включите это измерение в ключ или не помещайте ответ в общий кэш. Одна URL может иметь несколько корректных представлений; возврат неправильного является ошибкой приложения. Зафиксируйте таблицу: класс запроса, имя кэша, ожидаемая свежесть и резервный результат.
Резерв для навигации должен сообщать, насколько свежи данные. Воркер может вернуть сохранённую оболочку, но интерфейс должен показать офлайн‑режим и действие повтора, а не выдавать старую панель аккаунта за живой ответ сервера. Непрозрачные ответы и ресурсы других источников проверяйте отдельно. Не используйте кэш‑хранилище для осмотра частного содержимого чужого сайта.
Версии и обновление выпуска
Считайте имя кэша контрактом выпуска, например offline-shell-v7. В install создайте и заполните новый кэш, а в activate перечислите имена своей функции и удалите старые версии. Новый worker может оставаться в состоянии ожидания, пока старый управляет открытыми страницами; подробности есть в описании жизненного цикла MDN.
При ошибке обязательного ресурса отклоните установку, а не активируйте неполный выпуск. Необязательные ресурсы можно поместить в отдельный кэш с повторной попыткой. Очистка при активации должна сохранять текущую версию и удалять только имена собственного префикса. В журнале выпуска укажите версию скрипта, имена до и после активации и наличие ожидающего worker.
skipWaiting() и clients.claim() ускоряют начало работы нового worker, но старая вкладка может получить ответы для нового контракта. Используйте их после проверки совместимости; при сомнении оставьте worker ожидающим и попросите перезагрузить страницу в определённой точке. URL с хэшем содержимого или версией выпуска не дают незаметно заменить байты внутри прежнего имени.
Офлайн‑резерв и восстановление
Определите результат для оболочки, навигации, изображения, шрифта, чтения API и записи. Старое чтение может требовать метки времени и кнопки обновления. Запись стоит ставить в очередь только при идемпотентности или наличии ключа идемпотентности и видимого состояния повтора. Кэш‑хранилище само по себе не предоставляет надёжную очередь записи или разрешение конфликтов.
Различайте промах кэша и сохранённую ошибку. Не храните временный 500 или перенаправление авторизации как офлайн‑страницу. Перед cache.put() проверяйте статус и тип содержимого. При отсутствии резерва верните небольшой контролируемый документ с объяснением следующего действия.
После успешного повтора заменяйте старый ответ только после тех же проверок, что применялись исходно. Офлайн‑черновик храните в подходящем хранилище приложения и показывайте время синхронизации; не прячьте ожидающую запись в кэше, который удалит следующий выпуск. Проверяйте холодный, тёплый и деградировавший контексты, записывая состояние worker, имена, класс запроса, источник ответа и видимый результат без токенов и тел ответов.
Очистка, выход и контроль пользователя
Удаление является функцией. Предусмотрите отдельную операцию для устаревших выпусков и для аккаунтов или черновиков, чтобы выпуск не удалил офлайн‑работу, а выход не оставил данные аккаунта в оболочке. При выходе или смене аккаунта сначала завершите серверную сессию, затем попросите worker удалить кэши аккаунта, очистите память и уведомите другие вкладки. Проверьте сценарий с двумя открытыми вкладками.
Clear-Site-Data может запросить очистку категорий данных источника, но покрытие зависит от браузера и не заменяет очистку приложения. Cache-Control описывает HTTP‑кэш и не запрещает воркеру вызвать cache.put(). Код, записывающий в кэш‑хранилище, должен применить политику до сохранения.
Минимизируйте данные: храните только необходимый офлайн‑экрану ответ, не помещайте токены в тело и задайте срок для черновиков и медиа. Кнопка очистки должна объяснять, затрагивает ли она сессию, очередь работы или только статические ресурсы.
Тестирование с BotBrowser и границы
BotBrowser может создавать воспроизводимые контексты браузера с изолированным хранилищем и состоянием сессии, поэтому команда может сравнивать холодный, тёплый и вышедший контекст без переноса состояния между ними. См. документацию об изоляции нескольких аккаунтов и фиксируйте состояние воркера, имена кэшей и видимый резервный результат. BotBrowser поддерживает изолированные контексты для таких проверок, но не записывает, не версионирует, не очищает и не интерпретирует записи кэш‑хранилища, не гарантирует вытеснение браузером, доступность офлайн или корректность стратегии воркера; владельцем кэша и очистки остаётся приложение.
Используйте контекст без кэша, контекст после установки и контекст после обновления. Загрузите известную оболочку, отключите сеть в разрешённой тестом точке, проверьте офлайн‑метку, затем восстановите сеть и убедитесь, что старый ответ заменён только прошедшим проверки новым ответом. Повторите выход и смену аккаунта с двумя контекстами и вкладками. Сравнивайте имена и состояние worker, а не частные тела ответов.
Доказательства BotBrowser должны ограничиваться изоляцией, навигацией, доступным состоянием worker и проверками списка кэшей приложения. Успешное сравнение не доказывает одинаковое вытеснение во всех браузерах, корректность production‑worker или безопасное повторение офлайн‑записи; для этого нужны тесты приложения, покрытие браузеров и явное решение продукта.
Имя каждого кэша должно указывать назначение и версию.
Установка должна отклоняться при неполном обязательном ресурсе.
Для необязательных ресурсов нужна отдельная повторная попытка.
Активация может удалять только префикс своей функции.
Сохранённый ответ не доказывает использование сети.
Видимый резерв должен объяснять возможность повтора.
Ответ аккаунта не является общим ресурсом оболочки.
Две вкладки должны получить уведомление о смене аккаунта.
Очистка версии не должна удалять черновик.
Новый контекст помогает отделить прежнее состояние.
Тестовые записи не должны содержать токены и частные тела.
Публичные источники
Похожие статьи
Переведите BotBrowser из исследований в продакшн
Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.