Режим InjectManifest в Webpack

InjectManifest — это режим работы Workbox, позволяющий полностью контролировать структуру Service Worker, сохраняя при этом преимущества автоматической генерации кэша для ресурсов. В отличие от режима GenerateSW, где Service Worker создаётся полностью автоматически, InjectManifest предоставляет возможность писать собственный Service Worker с кастомной логикой и одновременно интегрировать в него манифест ресурсов для предзагрузки (precache).

Установка и настройка

Для использования Workbox в режиме InjectManifest с Webpack необходимо установить следующие пакеты:

npm install workbox-webpack-plugin --save-dev

В конфигурации Webpack подключается плагин InjectManifest:

const { InjectManifest } = require('workbox-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  plugins: [
    new InjectManifest({
      swSrc: './src/service-worker.js', // исходный SW с кастомной логикой
      swDest: 'service-worker.js',     // результат компиляции
      maximumFileSizeToCacheInBytes: 5 * 1024 * 1024, // лимит кэшируемых файлов
    }),
  ],
};

swSrc — путь к исходному Service Worker, который разработчик создаёт самостоятельно. swDest — путь, по которому будет создан сгенерированный Service Worker.

Структура кастомного Service Worker

Service Worker в режиме InjectManifest должен включать импорт методов Workbox, необходимых для управления кэшем и стратегиями загрузки. Обычно это делается с помощью workbox-core, workbox-precaching и workbox-routing:

import { precacheAndRoute } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';

// Предзагрузка ресурсов, автоматически внедряемых плагином InjectManifest
precacheAndRoute(self.__WB_MANIFEST);

// Пример кэширования API-запросов с использованием стратегии StaleWhileRevalidate
registerRoute(
  ({ url }) => url.origin === 'https://api.example.com',
  new StaleWhileRevalidate({
    cacheName: 'api-cache',
    plugins: [],
  })
);

Манифест ресурсов

InjectManifest автоматически генерирует массив объектов с ресурсами для предзагрузки, который помещается в глобальную переменную self.__WB_MANIFEST. Каждый объект содержит:

  • url — путь к ресурсу
  • revision — хэш версии файла

Использование precacheAndRoute(self.__WB_MANIFEST) гарантирует, что эти файлы будут закэшированы во время установки Service Worker и доступны офлайн.

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

Workbox предоставляет несколько встроенных стратегий кэширования, которые можно комбинировать в кастомном SW:

  • CacheFirst — сначала ищет ресурс в кэше, затем в сети. Подходит для неизменяемых файлов (например, шрифтов, изображений).
  • NetworkFirst — сначала пытается загрузить ресурс из сети, при неудаче использует кэш. Оптимально для API или динамического контента.
  • StaleWhileRevalidate — отдаёт кэш сразу и обновляет его из сети в фоне. Баланс между скоростью и актуальностью.

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

import { CacheFirst, NetworkFirst } from 'workbox-strategies';
import { registerRoute } from 'workbox-routing';

// Кэшируем статические изображения
registerRoute(
  ({ request }) => request.destination === 'image',
  new CacheFirst({ cacheName: 'images-cache' })
);

// Кэшируем динамический контент API
registerRoute(
  ({ url }) => url.pathname.startsWith('/api/'),
  new NetworkFirst({ cacheName: 'api-cache' })
);

Расширенные возможности

  1. Работа с плагинами Workbox — позволяют добавлять расширенные возможности, такие как автоочистка устаревшего кэша (ExpirationPlugin), кэширование только успешных ответов (CacheableResponsePlugin) и контроль максимального размера кэша.
import { ExpirationPlugin } from 'workbox-expiration';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';

registerRoute(
  ({ request }) => request.destination === 'image',
  new CacheFirst({
    cacheName: 'images-cache',
    plugins: [
      new CacheableResponsePlugin({ statuses: [0, 200] }),
      new ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 7 * 24 * 60 * 60 }),
    ],
  })
);
  1. Управление событиями Service Worker — добавление кастомной логики для install, activate, fetch событий позволяет гибко контролировать жизненный цикл и кэширование.
self.addEventListener('install', (event) => {
  console.log('Service Worker устанавливается');
});

self.addEventListener('activate', (event) => {
  console.log('Service Worker активирован');
});
  1. Оптимизация сборки Webpack — при использовании InjectManifest важно учитывать размер файлов. Плагин имеет опцию maximumFileSizeToCacheInBytes, которая предотвращает добавление слишком больших ресурсов в precache, что может замедлить установку SW.

Отличия InjectManifest от GenerateSW

  • Контроль кода — весь Service Worker пишется вручную, а не генерируется автоматически.
  • Предзагрузка ресурсов — все ресурсы, указанные в манифесте, внедряются автоматически.
  • Гибкость — можно использовать любые сторонние библиотеки и писать кастомную логику кэширования, не ограничиваясь функционалом Workbox.

Использование режима InjectManifest в Webpack обеспечивает идеальный баланс между полной кастомизацией Service Worker и автоматизацией кэширования, позволяя создавать производительные и надёжные PWA-приложения.