Динамическая конфигурация в зависимости от окружения

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


Основные параметры конфигурации

Sw-precache принимает объект конфигурации, который определяет:

  • staticFileGlobs — массив путей к статическим файлам, которые должны быть закэшированы.
  • stripPrefix — префикс пути, который нужно удалить при кэшировании.
  • runtimeCaching — правила кэширования для ресурсов, которые динамически загружаются.
  • navigateFallback — fallback для SPA (одностраничных приложений), когда запрашиваемый URL не найден.
  • handleFetch — включение или отключение перехвата fetch-запросов сервис-воркером.

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


Определение окружения

Для разделения конфигураций обычно используют переменные окружения:

const env = process.env.NODE_ENV || 'development';

На практике можно определить три режима:

  • development — локальная разработка.
  • staging — промежуточная среда для тестирования.
  • production — финальный релиз приложения.

В зависимости от значения NODE_ENV задаются разные правила кэширования и стратегии генерации сервис-воркера.


Пример динамической конфигурации

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

const env = process.env.NODE_ENV || 'development';

const config = {
  staticFileGlobs: ['public/**/*.{js,css,html,png,jpg,gif,svg}'],
  stripPrefix: 'public/',
  handleFetch: true,
  runtimeCaching: []
};

if (env === 'development') {
  config.handleFetch = false; // Отключаем перехват запросов в dev
  config.staticFileGlobs = ['public/js/**/*.js', 'public/css/**/*.css'];
  config.navigateFallback = null; // Не используем fallback
} else if (env === 'staging') {
  config.runtimeCaching.push({
    urlPattern: /\/api\/.*\/*.json/,
    handler: 'networkFirst'
  });
  config.navigateFallback = '/index.html';
} else if (env === 'production') {
  config.cacheId = 'my-app-cache';
  config.maximumFileSizeToCacheInBytes = 5 * 1024 * 1024; // 5MB
  config.runtimeCaching.push(
    {
      urlPattern: /\/api\/.*\/*.json/,
      handler: 'networkFirst'
    },
    {
      urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/,
      handler: 'cacheFirst'
    }
  );
  config.navigateFallback = '/index.html';
}

swPrecache.write('public/service-worker.js', config, err => {
  if (err) {
    console.error('Ошибка при генерации сервис-воркера:', err);
  } else {
    console.log('Сервис-воркер успешно сгенерирован для окружения:', env);
  }
});

В этом примере:

  • В development отключен перехват fetch-запросов, чтобы не кэшировать часто изменяющиеся ресурсы.
  • В staging используется стратегия networkFirst для API-запросов, чтобы тестировщики видели актуальные данные.
  • В production применяются более строгие правила кэширования и лимиты на размер файлов, плюс fallback для SPA.

Использование шаблонов для динамического контента

Для динамически генерируемых страниц или ресурсов полезно использовать параметр runtimeCaching. Он позволяет указывать:

  • urlPattern — регулярное выражение для URL ресурсов.
  • handler — стратегия кэширования (networkFirst, cacheFirst, fastest, networkOnly, cacheOnly).

Пример для продакшена:

config.runtimeCaching.push({
  urlPattern: /\/articles\/.*\.json/,
  handler: 'networkFirst'
});

Это позволяет всегда получать актуальные статьи, но при отсутствии сети использовать кэшированные версии.


Стратегия кэширования и размеры файлов

Важно различать кэширование статических и динамических ресурсов:

  • Статические файлы (CSS, JS, изображения) — лучше использовать cacheFirst, так как они редко изменяются.
  • Динамические данные (API, JSON) — лучше networkFirst, чтобы пользователь видел актуальную информацию.

Для оптимизации производительности в продакшене задаются ограничения:

config.maximumFileSizeToCacheInBytes = 5 * 1024 * 1024; // ограничение в 5 МБ

Автоматизация через скрипты сборки

Для удобства генерацию сервис-воркера можно интегрировать в npm-скрипты:

"scripts": {
  "build:dev": "NODE_ENV=development node generate-sw.js",
  "build:staging": "NODE_ENV=staging node generate-sw.js",
  "build:prod": "NODE_ENV=production node generate-sw.js"
}

Таким образом, при сборке проекта автоматически применяется нужная конфигурация.


Советы по поддержке разных окружений

  • Разделять настройки через функции: каждая среда получает отдельную функцию-конфигуратор.
  • Версионировать кэш: добавлять cacheId с номером версии, чтобы при обновлении приложения старый кэш автоматически инвалидировался.
  • Логировать ошибки при генерации сервис-воркера, чтобы не запускать старый кэш случайно.