Workbox предоставляет гибкий механизм для работы с кэшированием и управлением сетевыми запросами через сервис-воркеры. Одним из ключевых компонентов этой системы являются хуки жизненного цикла запроса (Lifecycle Hooks), которые позволяют вмешиваться в процесс обработки запросов на различных стадиях, изменять их поведение и управлять кэшированием.
Жизненный цикл запроса в Workbox можно разделить на несколько ключевых этапов:
beforeFetch – этап до выполнения сетевого запроса. Здесь можно модифицировать объект запроса, добавлять заголовки или перенаправлять запрос на другой URL.
fetchDidFail – срабатывает, если сетевой запрос завершился с ошибкой. Используется для обработки сбоев сети, fallback-логики и логирования.
cacheWillUpdate – срабатывает перед записью ответа в кэш. Позволяет контролировать, какой ответ будет кэшироваться, проверять статус кода, размер или тип контента.
cacheDidUpdate – срабатывает после успешной записи ответа в кэш. Подходит для уведомления других частей приложения о новых данных, например, для обновления индикаторов контента.
cachedResponseWillBeUsed – вызывается перед использованием кэшированного ответа. Можно вернуть кастомный ответ вместо того, что был найден в кэше, или добавить дополнительную логику проверки свежести.
requestWillFetch – вызывается перед отправкой сетевого запроса. Позволяет модифицировать запрос, добавлять токены авторизации или включать дополнительные параметры.
Модификация запроса перед отправкой:
import {registerRoute} from 'workbox-routing';
import {NetworkFirst} from 'workbox-strategies';
registerRoute(
({request}) => request.destination === 'script',
new NetworkFirst({
cacheName: 'js-cache',
plugins: [{
requestWillFetch: async ({request}) => {
const newRequest = new Request(request.url, {
...request,
headers: {
...request.headers,
'X-Custom-Header': 'MyHeaderValue'
}
});
return newRequest;
}
}]
})
);
Контроль кэширования ответов:
import {StaleWhileRevalidate} from 'workbox-strategies';
const cachePlugin = {
cacheWillUpdate: async ({response}) => {
if (response && response.status === 200 && response.type === 'basic') {
return response;
}
return null; // не кэшировать невалидные ответы
},
cacheDidUpdate: ({cacheName, request, oldResponse, newResponse}) => {
console.log(`Кэш обновлен: ${request.url}`);
}
};
registerRoute(
({request}) => request.destination === 'image',
new StaleWhileRevalidate({
cacheName: 'images-cache',
plugins: [cachePlugin]
})
);
Обработка неудачных сетевых запросов:
import {NetworkFirst} from 'workbox-strategies';
const fallbackPlugin = {
fetchDidFail: async ({originalRequest}) => {
console.error(`Ошибка при загрузке: ${originalRequest.url}`);
return caches.match('/offline.html'); // возвращаем offline-страницу
}
};
registerRoute(
({request}) => request.mode === 'navigate',
new NetworkFirst({
cacheName: 'pages-cache',
plugins: [fallbackPlugin]
})
);
request,
response, cacheName), что упрощает управление
кэшированием.Каждый хук реализуется через плагины Workbox,
которые можно передавать в стратегии кэширования
(NetworkFirst, CacheFirst,
StaleWhileRevalidate). Один плагин может реализовывать
несколько хуков, что обеспечивает гибкость и повторное
использование логики в разных стратегиях и маршрутах.
Пример комбинированного плагина:
const myPlugin = {
requestWillFetch: async ({request}) => {
return new Request(request, {headers: {'Authorization': 'Bearer TOKEN'}});
},
cacheWillUpdate: async ({response}) => response && response.status === 200 ? response : null,
cacheDidUpdate: ({request}) => console.log(`Обновлен кэш для ${request.url}`)
};
Этот подход позволяет централизованно управлять запросами и кэшированием, уменьшая дублирование кода и повышая предсказуемость поведения сервис-воркера.
Хотите, я подготовлю детальную схему жизненного цикла запроса с указанием всех хуков Workbox, чтобы наглядно видеть, когда какой хук срабатывает? Это сильно облегчает понимание и отладку сервис-воркеров.