Стратегии кеширования

Урок разбирает основные стратегии кеширования и объясняет, когда применять каждую.

Стратегия кеширования — это правило, по которому Service Worker в обработчике fetch решает, откуда взять ответ: из кеша, из сети или из обоих.

Зачем нужны разные стратегии

Не все ресурсы одинаковы. Логотип и CSS меняются редко — их выгодно отдавать из кеша мгновенно. А лента новостей должна быть свежей — её лучше брать из сети. Поэтому для разных типов запросов применяют разные стратегии.

Cache-first (сначала кеш)

Сначала ищем в кеше; если есть — отдаём, в сеть не идём. Если в кеше нет — идём в сеть и кладём ответ в кеш. Идеально для статики (CSS, JS, шрифты, иконки): быстро и экономит трафик.

self.addEventListener('fetch', function (event) {
  event.respondWith(
    caches.match(event.request).then(function (cached) {
      return cached || fetch(event.request);
    })
  );
});

Network-first (сначала сеть)

Сначала идём в сеть за свежими данными; если сети нет — отдаём из кеша. Подходит для часто меняющихся данных (лента, профиль), где свежесть важнее скорости.

self.addEventListener('fetch', function (event) {
  event.respondWith(
    fetch(event.request)
      .then(function (resp) {
        const copy = resp.clone();
        caches.open('api-v1').then(function (c) { c.put(event.request, copy); });
        return resp;
      })
      .catch(function () { return caches.match(event.request); })
  );
});

Stale-while-revalidate (отдать кеш, обновить в фоне)

Отдаём то, что в кеше (мгновенно), и параллельно идём в сеть, чтобы обновить кеш к следующему разу. Компромисс между скоростью и свежестью: пользователь видит контент сразу, а данные «догоняются» в фоне.

Stale-while-revalidate:
  запрос --> отдать из кеша СРАЗУ
          --> параллельно сходить в сеть
          --> обновить кеш для следующего раза

Сравнение стратегий

СтратегияКогда применять
cache-firstстатика: CSS, JS, шрифты, иконки
network-firstсвежие данные: лента, баланс, API
stale-while-revalidateконтент, где допустима лёгкая «несвежесть»: аватары, списки
cache-onlyресурсы, которые точно лежат в кеше (App Shell)
network-onlyто, что нельзя кешировать: оплата, аналитика

Как работает под капотом respondWith

Ключ к стратегиям — метод event.respondWith(promise) в обработчике fetch. Он говорит браузеру: «не ходи в сеть сам, я отвечу этим Promise». Внутри Promise вы и реализуете логику стратегии. Если respondWith не вызвать, браузер обработает запрос как обычно — напрямую в сеть, без вашего вмешательства.

Частые ошибки

  • Cache-first для динамики. Лента «застрянет» на старых данных — пользователь не увидит новое.
  • Network-first для статики. Каждый раз ждём сеть ради файлов, которые не меняются, — теряем скорость.
  • Кешировать неуспешные ответы. Перед cache.put проверяйте, что ответ успешен (resp.ok), иначе закешируете ошибку.

Итоги

  • Стратегия — правило выбора источника ответа в обработчике fetch.
  • cache-first — для статики; network-first — для свежих данных; stale-while-revalidate — компромисс.
  • Логику стратегии задаёт event.respondWith(...).
  • Подбирайте стратегию под тип ресурса; не кешируйте неуспешные ответы.
Проверьте себя
1. Какая стратегия лучше всего подходит для статики (CSS, шрифты, иконки)?
Anetwork-first
Bcache-first
Cnetwork-only
DНикакая, статику не кешируют
2. В чём идея стратегии stale-while-revalidate?
AНикогда не использовать сеть
BОтдать ответ из кеша сразу, а в фоне сходить в сеть и обновить кеш
CВсегда ждать сеть
DКешировать только ошибки
3. Какой метод позволяет Service Worker ответить на fetch своим способом?
Aevent.preventDefault()
Bevent.respondWith(promise)
Cevent.waitUntil(promise)
Devent.stopPropagation()