Интеграция с Webpack через sw-precache-webpack-plugin

sw-precache-webpack-plugin представляет собой связующее звено между сборщиком Webpack и механизмом Service Worker. Плагин анализирует результат сборки (bundle), извлекает список статических ресурсов и генерирует Service Worker-файл с преднастроенным списком кешируемых активов (precache manifest).

Основная задача — автоматизация:

  • формирования списка файлов для кеширования
  • генерации Service Worker-кода
  • управления версионированием ресурсов

В отличие от ручного написания Service Worker, подход с плагином устраняет необходимость поддерживать список файлов вручную и снижает риск ошибок при деплое.


Установка и базовая настройка

npm install sw-precache-webpack-plugin --save-dev

Подключение в конфигурации Webpack:

const path = require('path');
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  plugins: [
    new SWPrecacheWebpackPlugin({
      cacheId: 'my-app',
      filename: 'service-worker.js',
      staticFileGlobs: [
        'dist/**/*.html',
        'dist/**/*.css',
        'dist/**/*.js',
        'dist/images/**/*'
      ],
      minify: true,
      stripPrefix: 'dist/'
    })
  ]
};

Ключевые параметры конфигурации

cacheId

Уникальный идентификатор кеша. Используется для изоляции данных между различными приложениями или версиями.

cacheId: 'my-app'

filename

Имя генерируемого Service Worker файла:

filename: 'service-worker.js'

Файл будет помещён в директорию output.path.


staticFileGlobs

Массив путей (glob-шаблонов), определяющих, какие файлы попадут в precache:

staticFileGlobs: [
  'dist/**/*.js',
  'dist/**/*.css',
  'dist/**/*.html'
]

Поддерживаются шаблоны:

  • **/* — рекурсивный поиск
  • *.js — по расширению
  • конкретные файлы

stripPrefix

Удаляет указанный префикс из путей ресурсов перед записью в кеш:

stripPrefix: 'dist/'

Без этого параметра пути могли бы выглядеть как /dist/js/app.js, что не соответствует реальному URL.


minify

Минификация итогового Service Worker:

minify: true

Уменьшает размер файла и ускоряет загрузку.


Генерация precache manifest

Во время сборки плагин:

  1. Сканирует указанные файлы
  2. Вычисляет их хеш (revision)
  3. Формирует массив:
[
  {
    "url": "/bundle.js",
    "revision": "a1b2c3d4"
  },
  {
    "url": "/styles.css",
    "revision": "e5f6g7h8"
  }
]

Этот список встраивается в Service Worker и используется для:

  • определения изменений файлов
  • обновления кеша

Автоматическое обновление кеша

Механизм обновления основан на ревизиях:

  • При изменении файла меняется его hash
  • Service Worker обнаруживает несоответствие
  • Старый кеш удаляется
  • Новый файл загружается

Это решает проблему “залипания” старых версий ресурсов.


Настройка runtime caching

Помимо precache, плагин позволяет управлять кешированием динамических запросов:

runtimeCaching: [
  {
    urlPattern: /\/api\//,
    handler: 'networkFirst'
  },
  {
    urlPattern: /\.(png|jpg|jpeg|svg)$/,
    handler: 'cacheFirst'
  }
]

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

cacheFirst

  • сначала кеш
  • затем сеть (если нет в кеше)

Подходит для:

  • изображений
  • статических ресурсов

networkFirst

  • сначала сеть
  • fallback на кеш

Используется для:

  • API-запросов
  • динамических данных

fastest

  • одновременно сеть и кеш
  • возвращает первый ответ

Управление fallback-страницами

Настройка fallback для offline:

navigateFallback: '/index.html'

Используется в SPA (Single Page Application), где:

  • маршрутизация происходит на клиенте
  • сервер не знает о внутренних маршрутах

Игнорирование файлов

Можно исключить определённые ресурсы:

staticFileGlobsIgnorePatterns: [
  /\.map$/,
  /asset-manifest\.json$/
]

Это уменьшает размер кеша и ускоряет установку Service Worker.


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

maximumFileSizeToCacheInBytes: 4194304

По умолчанию:

  • ~2 MB

Увеличение лимита полезно для:

  • крупных изображений
  • шрифтов

Инъекция кастомного Service Worker кода

Плагин позволяет добавлять пользовательскую логику:

importScripts: ['custom-sw.js']

Файл custom-sw.js может содержать:

self.addEventListener('push', function(event) {
  // обработка push-уведомлений
});

Управление версионированием

Версионирование осуществляется автоматически через hash, но можно дополнительно контролировать:

dontCacheBustUrlsMatching: /\.\w{8}\./

Используется при:

  • использовании content hashing (например, app.a1b2c3d4.js)
  • предотвращении двойного контроля версий

Генерация Service Worker с шаблоном

templateFilePath: 'src/sw-template.js'

Позволяет:

  • использовать собственную структуру Service Worker
  • внедрять precache manifest в шаблон

Жизненный цикл Service Worker

Сгенерированный Service Worker проходит стандартные стадии:

  1. install

    • кеширование файлов из precache
  2. activate

    • удаление старых кешей
  3. fetch

    • перехват запросов

Плагин автоматически внедряет соответствующую логику.


Регистрация Service Worker в приложении

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js');
  });
}

Особенности работы с Webpack

Взаимодействие с output.publicPath

Если используется:

output: {
  publicPath: '/static/'
}

URL ресурсов в кеше будут формироваться с учётом этого префикса.


Работа с code splitting

Webpack генерирует динамические чанки:

  • 0.bundle.js
  • 1.bundle.js

Плагин автоматически включает их в precache, если они попадают под staticFileGlobs.


Совместимость с хешированием файлов

При использовании:

filename: '[name].[contenthash].js'
  • плагин корректно отслеживает изменения
  • кеш обновляется автоматически

Ограничения и нюансы

  • Не подходит для сложных сценариев runtime caching без кастомизации
  • Генерируемый код сложно модифицировать после сборки
  • Устаревание: библиотека считается предшественником более современной системы Workbox

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

new SWPrecacheWebpackPlugin({
  cacheId: 'advanced-app',
  filename: 'sw.js',
  staticFileGlobs: [
    'dist/**/*.{js,css,html,png,jpg}'
  ],
  stripPrefix: 'dist/',
  minify: true,
  runtimeCaching: [
    {
      urlPattern: /^https:\/\/api\.example\.com/,
      handler: 'networkFirst'
    },
    {
      urlPattern: /\.(png|jpg|jpeg|svg|gif)$/,
      handler: 'cacheFirst'
    }
  ],
  navigateFallback: '/index.html',
  maximumFileSizeToCacheInBytes: 5 * 1024 * 1024
})

Отладка и проверка

Используются инструменты браузера:

  • вкладка Application → Service Workers
  • вкладка Cache Storage

Проверяется:

  • регистрация Service Worker
  • содержимое кеша
  • обновление при новой сборке

Поведение при обновлении приложения

  1. Пользователь открывает приложение

  2. Service Worker кеширует ресурсы

  3. Выходит новая версия

  4. При следующей загрузке:

    • скачивается новый Service Worker
    • активируется после закрытия вкладок
    • обновляет кеш

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

self.skipWaiting();
self.clients.claim();

(через кастомный шаблон)


Переход на Workbox

sw-precache-webpack-plugin исторически предшествует более современной экосистеме Workbox. Основные различия:

  • Workbox предоставляет более гибкие API
  • поддерживает стратегии кеширования “из коробки”
  • имеет лучшую поддержку Webpack

Тем не менее, понимание работы sw-precache-webpack-plugin важно для:

  • поддержки legacy-проектов
  • изучения принципов precaching
  • понимания архитектуры Service Worker-интеграции с бандлерами