Обработчик networkFirst

Стратегия networkFirst в библиотеке sw-precache реализует модель, при которой первичный источник данных — сеть, а кэш используется как резервный вариант при недоступности сети или превышении времени ожидания. Такой подход особенно эффективен для динамического контента, где актуальность данных критична.


Принцип работы

Алгоритм networkFirst можно описать следующим образом:

  1. При поступлении запроса Service Worker пытается получить ответ из сети.

  2. Если сетевой запрос успешен:

    • ответ сохраняется в кэш (при соответствующих настройках);
    • ответ возвращается клиенту.
  3. Если сетевой запрос завершился ошибкой (например, отсутствует соединение):

    • происходит попытка извлечения ответа из кэша;
    • если кэш содержит подходящий ресурс — он возвращается;
    • если нет — возвращается ошибка или fallback-ресурс.

Поведение при таймауте

Одной из важных особенностей networkFirst является возможность задания времени ожидания сети. Если ответ от сервера не получен в течение заданного интервала:

  • стратегия переключается на кэш;
  • пользователь получает более быстрый отклик, пусть и потенциально устаревший.

Конфигурация в sw-precache

Настройка стратегии networkFirst осуществляется через параметр runtimeCaching в конфигурации:

module.exports = {
  runtimeCaching: [
    {
      urlPattern: /\/api\/.*$/,
      handler: 'networkFirst',
      options: {
        cache: {
          name: 'api-cache'
        },
        networkTimeoutSeconds: 3
      }
    }
  ]
};

Ключевые параметры

urlPattern

Определяет, какие запросы будут обрабатываться стратегией. Поддерживает регулярные выражения.

handler: 'networkFirst'

Указывает на использование стратегии с приоритетом сети.

options.cache.name

Имя кэша, в котором будут храниться ответы.

options.networkTimeoutSeconds

Максимальное время ожидания ответа от сети. После истечения этого времени используется кэш.


Сценарии применения

1. API-запросы

Актуальность данных имеет первостепенное значение:

urlPattern: /\/api\/data/,
handler: 'networkFirst'

2. HTML-страницы

При использовании SPA или SSR важно загружать свежую версию страницы:

urlPattern: /\.html$/,
handler: 'networkFirst'

3. Пользовательский контент

Данные профиля, сообщения, уведомления:

  • сначала запрашиваются с сервера;
  • при отсутствии сети — берутся из кэша.

Сравнение с другими стратегиями

Стратегия Приоритет Использование кэша
cacheFirst Кэш Основной источник
networkFirst Сеть Резерв
fastest Оба Кто быстрее
networkOnly Сеть Не используется

Управление кэшированием

В networkFirst важно контролировать, какие ответы сохраняются:

options: {
  cache: {
    name: 'dynamic-cache',
    maxEntries: 50,
    maxAgeSeconds: 300
  }
}

Параметры:

  • maxEntries — ограничение количества записей;
  • maxAgeSeconds — срок жизни кэшированных данных.

Это предотвращает переполнение хранилища и устаревание данных.


Обработка ошибок

Если ни сеть, ни кэш не дали результата:

  • возвращается стандартная ошибка;
  • возможно использование fallback-ресурсов (например, offline-страницы).

Пример расширенной логики:

self.addEventListener('fetch', event => {
  event.respondWith(
    fetch(event.request)
      .then(response => {
        return caches.open('dynamic').then(cache => {
          cache.put(event.request, response.clone());
          return response;
        });
      })
      .catch(() => {
        return caches.match(event.request);
      })
  );
});

Оптимизация производительности

Использование таймаута

Позволяет избежать долгого ожидания медленной сети:

networkTimeoutSeconds: 2

Разделение кэшей

Разные типы ресурсов должны храниться отдельно:

  • api-cache
  • html-cache
  • image-cache

Ограничение кэша

Предотвращает рост использования памяти.


Проблемы и ограничения

1. Задержки при слабой сети

Приоритет сети может привести к медленной загрузке, если соединение нестабильно.

2. Неактуальность кэша

Если сеть недоступна, пользователь получает устаревшие данные.

3. Сложность настройки

Требуется баланс между таймаутами, размером кэша и частотой обновлений.


Расширенные подходы

Комбинирование стратегий

Можно использовать networkFirst только для API, а для статических ресурсов — cacheFirst.

Условная логика

Разные стратегии в зависимости от типа запроса:

runtimeCaching: [
  {
    urlPattern: /\/api\//,
    handler: 'networkFirst'
  },
  {
    urlPattern: /\.(js|css)$/,
    handler: 'cacheFirst'
  }
]

Практические рекомендации

  • использовать networkFirst для динамического контента;
  • обязательно задавать networkTimeoutSeconds;
  • ограничивать размер кэша;
  • избегать применения для статических файлов;
  • тестировать поведение в offline-режиме.

Внутренний механизм

networkFirst в sw-precache реализуется через последовательную попытку:

  1. fetch()
  2. cache.match()

С сохранением успешных сетевых ответов через:

cache.put(request, response.clone());

Клонирование необходимо, так как поток ответа может быть использован только один раз.


Итоговая модель

  • Сеть — основной источник
  • Кэш — резерв
  • Таймаут — механизм ускорения
  • Гибкость — через конфигурацию

Такой подход обеспечивает баланс между актуальностью данных и устойчивостью приложения к сетевым сбоям.