В веб-приложениях, использующих Service Worker для кэширования и оффлайн-доступа, частой проблемой является временная недоступность ресурсов из-за сетевых ошибок. Workbox предоставляет встроенные механизмы для управления повторными попытками запросов, что позволяет повысить надежность приложения без ручного написания сложной логики. Основная цель — уменьшение числа отказов при загрузке ресурсов и улучшение пользовательского опыта.
Workbox включает модуль workbox-strategies, который
позволяет настраивать поведение повторных запросов через объект
RetryableResponse и опции стратегий.
Пример базовой конфигурации повторных попыток:
import { NetworkFirst } from 'workbox-strategies';
import { registerRoute } from 'workbox-routing';
import { ExpirationPlugin } from 'workbox-expiration';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
const networkFirstStrategy = new NetworkFirst({
cacheName: 'dynamic-resources',
networkTimeoutSeconds: 5,
plugins: [
new ExpirationPlugin({
maxEntries: 100,
maxAgeSeconds: 24 * 60 * 60
}),
new CacheableResponsePlugin({
statuses: [0, 200]
})
]
});
registerRoute(
({ request }) => request.destination === 'script' || request.destination === 'style',
networkFirstStrategy
);
В этом примере NetworkFirst стратегия сначала пытается
загрузить ресурс из сети. Если сетевой запрос не удается в течение 5
секунд, используется кэш. Плагин CacheableResponsePlugin
гарантирует, что в кэш попадут только успешные ответы, а
ExpirationPlugin управляет ограничениями хранения.
RetryPlugin для автоматизации повторовWorkbox предоставляет workbox-background-sync, который
позволяет выполнять повторные попытки асинхронно, даже если пользователь
покидает страницу. Для сетевых запросов в реальном времени можно
использовать сторонние плагины, реализующие retry-логику.
Пример использования RetryPlugin для управления
повторными запросами:
import { StaleWhileRevalidate } from 'workbox-strategies';
import { registerRoute } from 'workbox-routing';
import { Plugin } from 'workbox-core';
class RetryPlugin extends Plugin {
constructor({ maxRetries = 3, retryDelay = 1000 }) {
super();
this.maxRetries = maxRetries;
this.retryDelay = retryDelay;
}
async fetchDidFail({ request }) {
let attempt = 0;
while (attempt < this.maxRetries) {
attempt++;
try {
await new Promise(resolve => setTimeout(resolve, this.retryDelay));
const response = await fetch(request);
if (response.ok) return response;
} catch (err) {
continue;
}
}
throw new Error(`Resource ${request.url} failed after ${this.maxRetries} attempts`);
}
}
registerRoute(
({ request }) => request.destination === 'image',
new StaleWhileRevalidate({
cacheName: 'images-cache',
plugins: [new RetryPlugin({ maxRetries: 5, retryDelay: 2000 })]
})
);
В этом примере при сбое загрузки изображения запрос повторяется до 5 раз с интервалом в 2 секунды. Если все попытки неудачны, выбрасывается исключение, которое может быть обработано другими плагинами или логикой Service Worker.
Для ресурсов, критически важных для работы приложения (например, отправка форм или данных пользователя), лучше использовать Background Sync:
import { BackgroundSyncPlugin } from 'workbox-background-sync';
import { NetworkOnly } from 'workbox-strategies';
import { registerRoute } from 'workbox-routing';
const bgSyncPlugin = new BackgroundSyncPlugin('formQueue', {
maxRetentionTime: 24 * 60 // минуты
});
registerRoute(
/\/api\/submit-form/,
new NetworkOnly({
plugins: [bgSyncPlugin]
}),
'POST'
);
Background Sync автоматически повторяет отправку запроса при восстановлении сети. Это позволяет полностью избежать потери данных при временном отсутствии соединения, в отличие от простых таймаутов и retry-плагинов.
Для понимания поведения повторных попыток полезно логировать события
fetchDidFail, sync и
responseWillBeUsed. Workbox поддерживает добавление
кастомных логов через плагины:
class LoggingPlugin extends Plugin {
async fetchDidFail({ request }) {
console.warn(`Fetch failed for ${request.url}`);
}
async syncDidComplete({ queue }) {
console.info(`Background Sync completed for ${queue.name}`);
}
}
Подключение такого плагина к стратегии позволяет видеть, какие ресурсы терпят неудачу и сколько раз происходят повторные попытки.
NetworkFirst
с retry и кэшем для оффлайн-доступа.StaleWhileRevalidate +
RetryPlugin для визуальных элементов, где некритична последняя
версия.NetworkOnly +
Background Sync для сохранения данных пользователей.Такой подход обеспечивает гибкость и минимизирует потерю данных при сетевых сбоях.
fetchDidFail и Background Sync.Обработка неудачных повторных попыток — ключевой инструмент для стабильности современных PWA, особенно при работе с мобильными сетями с нестабильным соединением.