Интеграция с npm scripts без таск-менеджера

Использование npm scripts позволяет отказаться от внешних таск-менеджеров (таких как Gulp или Grunt) и централизовать процесс сборки в package.json. Для библиотеки Sw-precache это особенно удобно, поскольку генерация service worker — это, как правило, финальный шаг сборки проекта.

Ключевая идея — встроить вызов sw-precache в цепочку команд, выполняемых через npm run.


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

Установка пакета выполняется как dev-зависимость:

npm install --save-dev sw-precache

После установки становится доступен CLI-интерфейс, который можно вызывать напрямую из scripts.


Минимальная интеграция через CLI

В package.json добавляется скрипт:

{
  "scripts": {
    "build-sw": "sw-precache --config=sw-precache-config.js"
  }
}

Файл конфигурации sw-precache-config.js содержит параметры генерации:

module.exports = {
  staticFileGlobs: [
    'dist/**/*.{js,html,css,png,jpg,gif,svg}'
  ],
  stripPrefix: 'dist/',
  runtimeCaching: [
    {
      urlPattern: /^https:\/\/api\.example\.com\//,
      handler: 'networkFirst'
    }
  ]
};

Встраивание в общий процесс сборки

Чаще всего генерация service worker должна выполняться после сборки проекта. Это реализуется через последовательное выполнение команд:

{
  "scripts": {
    "build": "webpack --mode production",
    "postbuild": "npm run build-sw",
    "build-sw": "sw-precache --config=sw-precache-config.js"
  }
}

Особенность npm scripts:

  • postbuild автоматически вызывается после build
  • не требуется дополнительная логика

Таким образом, команда:

npm run build

выполнит:

  1. сборку проекта
  2. генерацию service worker

Управление путями и окружениями

В реальных проектах часто требуется учитывать разные окружения: development, staging, production.

Пример с использованием переменных окружения:

{
  "scripts": {
    "build": "NODE_ENV=production webpack",
    "build-sw": "NODE_ENV=production sw-precache --config=sw-precache-config.js"
  }
}

В конфигурации:

const isProd = process.env.NODE_ENV === 'production';

module.exports = {
  staticFileGlobs: isProd
    ? ['dist/**/*']
    : ['dist/**/*.{js,html}'],
  stripPrefix: 'dist/'
};

Кроссплатформенность (Windows / Unix)

Переменные окружения работают по-разному:

  • Unix (Linux/macOS): NODE_ENV=production
  • Windows: set NODE_ENV=production

Для унификации используется пакет cross-env:

npm install --save-dev cross-env
{
  "scripts": {
    "build": "cross-env NODE_ENV=production webpack",
    "build-sw": "cross-env NODE_ENV=production sw-precache --config=sw-precache-config.js"
  }
}

Генерация service worker без отдельного файла конфигурации

CLI позволяет передавать параметры напрямую:

{
  "scripts": {
    "build-sw": "sw-precache dist --static-file-globs 'dist/**/*.{js,html,css}' --strip-prefix dist"
  }
}

Однако такой подход:

  • ухудшает читаемость
  • усложняет поддержку
  • не подходит для сложных конфигураций

Использование .js-конфига предпочтительнее.


Инкрементальная сборка и кеширование

Sw-precache автоматически генерирует хэши для файлов и обновляет service worker при изменениях. Важно учитывать:

  • service worker должен генерироваться после всех изменений файлов
  • любые дополнительные шаги (минификация, копирование) должны завершиться заранее

Типичная цепочка:

{
  "scripts": {
    "clean": "rimraf dist",
    "build": "webpack",
    "copy-assets": "cp -R public dist",
    "build-sw": "sw-precache --config=sw-precache-config.js",
    "start-build": "npm run clean && npm run build && npm run copy-assets && npm run build-sw"
  }
}

Использование npm-run-all для сложных сценариев

При необходимости параллельных или последовательных задач:

npm install --save-dev npm-run-all
{
  "scripts": {
    "build": "webpack",
    "assets": "node copyAssets.js",
    "sw": "sw-precache --config=sw-precache-config.js",
    "build:all": "run-s build assets sw"
  }
}
  • run-s — последовательное выполнение
  • run-p — параллельное

Автоматическое обновление service worker при разработке

Sw-precache не предназначен для разработки в реальном времени, но можно добавить скрипт для пересборки:

{
  "scripts": {
    "watch": "webpack --watch",
    "watch-sw": "nodemon --watch dist --exec \"npm run build-sw\""
  }
}

Требуется установка:

npm install --save-dev nodemon

Включение service worker в HTML

После генерации файл обычно сохраняется как service-worker.js в папке dist.

Регистрация:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js');
}

Важно:

  • путь должен соответствовать stripPrefix
  • service worker работает только по HTTPS (или localhost)

Контроль версии service worker

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

module.exports = {
  cacheId: 'my-app-v1',
  staticFileGlobs: ['dist/**/*'],
  stripPrefix: 'dist/'
};

Изменение cacheId принудительно обновляет кеш.


Обработка ошибок в npm scripts

Ошибки выполнения скриптов автоматически останавливают цепочку:

{
  "scripts": {
    "build": "webpack",
    "build-sw": "sw-precache --config=sw-precache-config.js"
  }
}

Если webpack завершится с ошибкой:

  • build-sw не выполнится

Для принудительного выполнения:

{
  "scripts": {
    "build": "webpack || true",
    "build-sw": "sw-precache --config=sw-precache-config.js"
  }
}

Логирование и отладка

Sw-precache CLI выводит базовую информацию. Для расширенного контроля можно использовать Node API:

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

swPrecache.write('dist/service-worker.js', {
  staticFileGlobs: ['dist/**/*']
}).then(() => {
  console.log('Service worker сгенерирован');
});

И подключить в scripts:

{
  "scripts": {
    "build-sw": "node build-sw.js"
  }
}

Оптимизация структуры проекта

Рекомендуемая структура:

project/
├── src/
├── dist/
├── sw-precache-config.js
├── build-sw.js (опционально)
├── package.json

Практика интеграции без лишних зависимостей

Ключевые принципы:

  • использование стандартных возможностей npm
  • минимизация сторонних инструментов
  • явная последовательность шагов
  • конфигурация в JavaScript вместо CLI-строк

Типовой production-скрипт

{
  "scripts": {
    "clean": "rimraf dist",
    "build": "webpack --mode production",
    "postbuild": "sw-precache --config=sw-precache-config.js",
    "start": "npm run clean && npm run build"
  }
}

Такой подход обеспечивает:

  • воспроизводимость сборки
  • простоту CI/CD интеграции
  • отсутствие зависимости от таск-менеджеров
  • прозрачность всех этапов сборки