Cache API

Key/value хранилище где ключ — Request, значение — Response. Сердце offline-режима в Service Worker.

Что это

Глобал caches (доступен в Window и в Service Worker, secure context). Несколько именованных кэшей, каждый — Cache объект. Не путать с HTTP cache браузера — это явный программный кэш, ты решаешь что и когда лежит. Persistent, переживает перезагрузку.

Базовое использование

// Прогрев в Service Worker install
const CACHE = 'app-v1';
const cache = await caches.open(CACHE);
await cache.addAll([
  '/',
  '/app.js',
  '/styles.css',
  '/icon.png',
]);

// Получить
const cached = await cache.match('/app.js');
// или сразу из всех кэшей
const any = await caches.match('/app.js');

// Положить ответ от сети
const res = await fetch('/api/data');
await cache.put('/api/data', res.clone()); // res нужен дважды — клонируем

// Удалить запись
await cache.delete('/old.js');

// Удалить весь кэш по имени
await caches.delete('app-v0');

// Список кэшей
const names = await caches.keys();

Стратегии в fetch handler

// Cache-first (статика)
const cacheFirst = async (req) =>
  (await caches.match(req)) || fetch(req);

// Network-first (API)
const networkFirst = async (req) => {
  try {
    const res = await fetch(req);
    const cache = await caches.open('api');
    cache.put(req, res.clone());
    return res;
  } catch {
    return caches.match(req);
  }
};

// Stale-while-revalidate
const swr = async (req) => {
  const cached = await caches.match(req);
  const fresh = fetch(req).then((res) => {
    caches.open('app').then((c) => c.put(req, res.clone()));
    return res;
  });
  return cached || fresh;
};

Поддержка

Все современные браузеры. Secure context (HTTPS или localhost).

Подводные камни

  • Response body — стрим: после первого чтения пустой. res.clone() ДО передачи в cache.put
  • POST-запросы по умолчанию нельзя класть в Cache API — только GET (в spec, в Chrome иногда работает)
  • Квота меняется браузером, обычно ~60% свободного диска; превышение → QuotaExceededError
  • Не путать с HTTP cache: Cache API не учитывает Cache-Control заголовки сам
  • caches.match без указания кэша ищет по всем — медленнее чем cache.match

Используется в bootcamp

  • Любая PWA-задача: кэширование статики (HTML/JS/CSS) + offline-страница

Ссылки

🎓 Источники

См. также