Как сохранить кэш между сессиями пользователя в браузере?
Что проверяют
Знаете ли вы, какие хранилища браузера переживают закрытие вкладки, и понимаете ли их пределы. Следом почти всегда спрашивают, как такой кэш инвалидировать и что в нём хранить нельзя.
Как отвечать
Сначала уточните, что кэшируется: статика, ответы API или состояние интерфейса. От этого зависит инструмент:
- HTTP-кэш: статике с хэшем в имени файла ставят
Cache-Control: max-age=31536000, immutable, для HTML и APIno-cacheсETag, тогда браузер переспрашивает сервер и получает дешёвый304; localStorage: синхронный, хранит только строки, лимит около 5 МБ на origin. Годится для настроек и небольших справочников, но большойJSON.parseблокирует главный поток;- IndexedDB: асинхронная, хранит объекты и
Blob, объёмы на порядки больше. Голый API неудобен, поэтому берут обёртку вродеidbили Dexie; - Cache API и Service Worker: кэш целых ответов, основа офлайн-режима и стратегии stale-while-revalidate;
sessionStorage: живёт в пределах вкладки, поэтому задачу «между сессиями» не решает, и это стоит сказать прямо.
Каждой записи нужны версия схемы и срок годности: при несовпадении версии кэш сбрасывается, а не падает на старом формате. В React-проекте это часто уже решено: у TanStack Query есть persistQueryClient с персистером в localStorage или IndexedDB и параметром maxAge.
Хранилище не вечное. При нехватке места браузер вытесняет данные сайта, navigator.storage.persist() просит сделать хранилище постоянным, navigator.storage.estimate() показывает квоту. Safari стирает всё, что записал скрипт, если с сайтом не взаимодействовали семь дней.
Где спотыкаются
Кладут в localStorage токены и персональные данные. Любой XSS прочитает их одной строкой, для сессии надёжнее кука с HttpOnly.
Кэшируют без версии и срока. После релиза клиент читает данные старого формата, и приложение падает у тех, кто давно не заходил.
Не обрабатывают QuotaExceededError и режимы, где запись не проходит. Кэш должен быть ускорителем: если он недоступен, приложение обязано работать и без него.