Как реализовать кэширование ответов от бэкенда на фронтенде?
Что проверяют
Понимаете ли вы, что кэш на клиенте состоит из нескольких слоёв, и умеете ли думать про устаревание данных, а не только про их сохранение. Следом обычно спрашивают, как обновить кэш после мутации и как не показать чужие данные после смены пользователя.
Как отвечать
Идите снизу вверх:
- HTTP-кэш браузера: сервер управляет им заголовками.
Cache-Control: max-age=60отдаёт ответ без запроса,ETagсIf-None-Matchдаёт дешёвый ответ 304,stale-while-revalidateпоказывает старое и обновляет в фоне. Часто это решает задачу без строчки JS; - кэш в памяти приложения: TanStack Query, SWR, RTK Query или Apollo для GraphQL. Они хранят ответы по ключу из параметров запроса, склеивают одновременные запросы в один и умеют перезапрашивать данные при фокусе окна и после мутаций;
- постоянное хранилище: IndexedDB для больших объёмов и оффлайна, Service Worker с Cache API (часто через Workbox) для стратегий cache-first и network-first.
У TanStack Query назовите два параметра: staleTime (по умолчанию 0, данные сразу считаются устаревшими) и gcTime (по умолчанию 5 минут, в v5 так переименовали cacheTime). После мутации вызывается queryClient.invalidateQueries по нужному ключу.
Если пишете руками, кэшируйте промис, а не результат: второй вызов во время первого запроса получит тот же промис, и сеть не пойдёт дважды. Храните время записи и проверяйте TTL при чтении.
Где спотыкаются
Складывают всё в localStorage без срока жизни. Он синхронный и блокирует основной поток на больших JSON, держит только строки, обычно ограничен примерно 5 МБ на источник, а данные в нём живут вечно.
Кладут в постоянный кэш персональные данные и токены. Их прочитает любой скрипт при XSS, а после выхода из аккаунта они остаются в браузере следующего пользователя.
Строят ключ кэша только из URL, забывая про параметры, язык или пользователя, и показывают один ответ вместо другого.