Комбинирование precache и runtimeCaching

Библиотека Sw-precache используется для генерации сервис-воркера, который позволяет кэшировать статические ресурсы и управлять стратегиями кэширования в браузере. Одной из мощных возможностей является комбинирование precache и runtimeCaching для оптимизации производительности и обеспечения оффлайн-доступа.

Precache предназначен для кэширования файлов на этапе установки сервис-воркера. Обычно это статические ресурсы: HTML, CSS, JavaScript, изображения, шрифты. Они гарантированно будут доступны даже при отсутствии интернет-соединения.

RuntimeCaching используется для динамических ресурсов, которые не известны заранее. Это API-запросы, данные с серверов, изображения, подгружаемые по мере взаимодействия пользователя с приложением.


Настройка precache

Для precache в Sw-precache используется опция staticFileGlobs. Она определяет список файлов и шаблонов, которые должны быть автоматически кэшированы:

const swPrecache = require('sw-precache');

swPrecache.write('service-worker.js', {
  staticFileGlobs: [
    'index.html',
    'css/**/*.css',
    'js/**/*.js',
    'images/**/*.{png,jpg,gif,svg}'
  ],
  stripPrefix: 'dist/',
  cacheId: 'my-app-cache'
});

Ключевые моменты:

  • staticFileGlobs поддерживает шаблоны с использованием ** для рекурсивного обхода каталогов.
  • stripPrefix позволяет удалить часть пути при сохранении ресурсов в кэше.
  • cacheId задаёт уникальный идентификатор кэша, чтобы избежать конфликтов при обновлениях.

Настройка runtimeCaching

Опция runtimeCaching позволяет задать правила кэширования для ресурсов, которые запрашиваются динамически. Каждое правило включает urlPattern, handler, и опционально дополнительные параметры.

swPrecache.write('service-worker.js', {
  runtimeCaching: [
    {
      urlPattern: /^https:\/\/api\.example\.com\/data/,
      handler: 'networkFirst',
      options: {
        cache: {
          name: 'api-cache',
          maxEntries: 50,
          maxAgeSeconds: 300
        }
      }
    },
    {
      urlPattern: /^https:\/\/cdn\.example\.com\/images/,
      handler: 'cacheFirst',
      options: {
        cache: {
          name: 'images-cache',
          maxEntries: 100,
          maxAgeSeconds: 86400
        }
      }
    }
  ]
});

Handler-стратегии:

  • networkFirst — сначала пробует загрузить ресурс с сети, при неудаче берёт из кэша. Подходит для данных, которые часто обновляются.
  • cacheFirst — сначала проверяет кэш, если ресурса нет, делает запрос к сети. Подходит для изображений, шрифтов и других редко изменяемых файлов.
  • fastest — параллельно проверяет сеть и кэш, отдаёт первый доступный результат. Полезно для снижения времени отклика.
  • networkOnly и cacheOnly — специализированные стратегии для строгого контроля.

Комбинирование precache и runtimeCaching

Применение precache и runtimeCaching одновременно позволяет добиться полной гибкости:

  1. Статические файлы кэшируются заранее через staticFileGlobs, обеспечивая мгновенный оффлайн-доступ.
  2. Динамические данные и медиа обрабатываются через runtimeCaching с индивидуальными стратегиями.
  3. Обновление кэшей управляется автоматически: при изменении файла в staticFileGlobs сервис-воркер пересоздаёт кэш, не затрагивая runtime-кэш, что минимизирует трафик.

Пример комбинированной конфигурации:

swPrecache.write('service-worker.js', {
  staticFileGlobs: [
    'index.html',
    'css/**/*.css',
    'js/**/*.js'
  ],
  stripPrefix: 'dist/',
  runtimeCaching: [
    {
      urlPattern: /\/api\/.*$/,
      handler: 'networkFirst',
      options: {
        cache: {
          name: 'api-cache',
          maxEntries: 30
        }
      }
    },
    {
      urlPattern: /\/images\/.*$/,
      handler: 'cacheFirst',
      options: {
        cache: {
          name: 'images-cache',
          maxEntries: 100,
          maxAgeSeconds: 604800
        }
      }
    }
  ]
});

Лучшие практики

  • Разделение стратегий по типу ресурсов. Статические файлы через precache, динамические через runtimeCaching.
  • Ограничение объёма кэша. Использовать maxEntries и maxAgeSeconds для предотвращения переполнения.
  • Версионирование кэша. Изменение cacheId при крупных обновлениях помогает гарантировать обновление ресурсов.
  • Совмещение стратегий. Например, изображения могут использовать cacheFirst, а JSON-данные с API — networkFirst для актуальности.
  • Логирование и отладка. Проверять кэш и обработку ошибок через console.log и DevTools, чтобы убедиться, что precache и runtimeCaching работают корректно.

Сценарии использования

  1. SPA (Single Page Application): HTML и JS через precache, API-запросы через networkFirst, изображения через cacheFirst.
  2. Контентные сайты: Основные страницы и CSS через precache, статьи и медиаконтент через runtimeCaching.
  3. Оффлайн-приложения: Все ключевые ресурсы через precache, данные с сервера через runtimeCaching с сетевой стратегией fallback к кэшу.

Тонкости реализации

  • runtimeCaching выполняется только после установки и активации сервис-воркера, в отличие от precache, который происходит сразу.
  • Конфликт URL-правил может привести к перезаписи кэшей. Важно точно задавать urlPattern.
  • Для динамического кэширования полезно использовать ignoreSearch и directoryIndex для нормализации URL.
  • Sw-precache автоматически генерирует уникальные хэши для precache файлов, что упрощает управление версиями.

Комбинирование precache и runtimeCaching позволяет создавать быстрые, устойчивые к оффлайну веб-приложения с точным контролем стратегий кэширования для каждого типа ресурсов.