Для интеграции sw-precache с Gulp необходимо сначала установить пакет через npm:
npm install --save-dev sw-precache gulp
После установки создаётся файл Gulp задачи, который будет генерировать сервис-воркеры для кэширования статических ресурсов. Базовая конфигурация выглядит следующим образом:
const gulp = require('gulp');
const swPrecache = require('sw-precache');
gulp.task('generate-service-worker', function(callback) {
swPrecache.write('dist/service-worker.js', {
staticFileGlobs: [
'dist/**/*.html',
'dist/**/*.js',
'dist/**/*.css',
'dist/images/**/*.{png,jpg,gif,svg}'
],
stripPrefix: 'dist/',
runtimeCaching: [{
urlPattern: /\/api\/.*$/,
handler: 'networkFirst'
}]
}, callback);
});
Ключевые моменты конфигурации:
staticFileGlobs — массив шаблонов для файлов, которые
должны быть кэшированы при установке сервис-воркера.stripPrefix — убирает часть пути при сохранении файлов
в кэше, что упрощает их адресацию.runtimeCaching — массив правил для динамического
кэширования, позволяющий управлять стратегиями
(networkFirst, cacheFirst и др.).1. Смешанное кэширование с версияцией
Чтобы управлять версиями кэша и гарантировать корректное обновление ресурсов:
const cacheId = 'my-app-cache';
const cacheVersion = 'v1';
swPrecache.write('dist/service-worker.js', {
cacheId: `${cacheId}-${cacheVersion}`,
staticFileGlobs: [
'dist/**/*.html',
'dist/**/*.css',
'dist/**/*.js'
],
stripPrefix: 'dist/',
dynamicUrlToDependencies: {
'/index.html': ['dist/index.html']
},
runtimeCaching: [
{
urlPattern: /\/api\/.*$/,
handler: 'networkFirst'
}
]
});
cacheId позволяет разграничивать кэши между разными
проектами.dynamicUrlToDependencies используется для обновления
конкретных URL при изменении файлов зависимостей.2. Кэширование с обработкой версии хеша
Для ресурсов с хешированными именами можно исключить их из переиндексации, используя регулярные выражения:
staticFileGlobs: [
'dist/**/*.{css,js,png,jpg,gif,svg}',
'!dist/**/*.map'
],
.map файлов предотвращает лишнее
кэширование, ускоряя установку сервис-воркера.gulp-rev, и передавать итоговые
файлы в staticFileGlobs.1. Автоматическая генерация при сборке проекта
gulp.task('build', gulp.series('clean', 'styles', 'scripts', 'images', 'generate-service-worker'));
2. Инкрементальное обновление кэша
Можно использовать опцию stripPrefixMulti для разных
директорий:
swPrecache.write('dist/service-worker.js', {
stripPrefixMulti: {
'dist/': '',
'bower_components/': 'vendor/'
},
staticFileGlobs: [
'dist/**/*.html',
'dist/**/*.js',
'bower_components/**/*.js'
]
});
sw-precache поддерживает несколько стратегий кэширования
для динамических запросов:
Пример продвинутой конфигурации:
runtimeCaching: [
{
urlPattern: /\/api\/v1\/users/,
handler: 'networkFirst',
options: {
cache: {
maxEntries: 50,
name: 'users-api-cache'
}
}
},
{
urlPattern: /\/images\/.*\.(png|jpg|gif|svg)/,
handler: 'cacheFirst',
options: {
cache: {
maxEntries: 100,
maxAgeSeconds: 60 * 60 * 24 * 30 // 30 дней
}
}
}
]
maxEntries и maxAgeSeconds
позволяет контролировать размер кэша и срок хранения.Для полноценной PWA-оптимизации сервис-воркер, сгенерированный через sw-precache, можно:
index.html:if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js');
}
skipWaiting и clientsClaim через ручное
редактирование сгенерированного файла или через шаблон:self.addEventListener('install', event => {
self.skipWaiting();
});
self.addEventListener('activate', event => {
event.waitUntil(clients.claim());
});
gulp-plumber для безопасного выполнения
задачи:const plumber = require('gulp-plumber');
gulp.task('generate-service-worker', function(callback) {
return gulp.src('dist')
.pipe(plumber())
.pipe(swPrecache.write('service-worker.js', {/* конфиг */}, callback));
});
Логи ошибок выводятся в консоль, что позволяет быстро локализовать проблемы при неверной конфигурации шаблонов или стратегии кэширования.
Для отладки можно включить verbose режим:
swPrecache.write('dist/service-worker.js', {
verbose: true,
staticFileGlobs: ['dist/**/*.{js,css,html}']
});