Workbox позволяет эффективно управлять версиями кэша с помощью
стратегий precache и runtime caching,
что обеспечивает возможность отката к предыдущей версии приложения при
необходимости. Основной механизм — это указание уникального
revision для каждого ресурса. Например, при сборке
приложения с использованием Workbox CLI или Workbox Webpack Plugin
автоматически генерируется манифест ресурсов с хэшами:
workbox.precaching.precacheAndRoute([
{ url: '/index.html', revision: 'a1b2c3d4' },
{ url: '/styles/main.css', revision: 'e5f6g7h8' },
{ url: '/scripts/app.js', revision: 'i9j0k1l2' },
]);
Ключевой момент: изменение содержимого файла
изменяет revision, что позволяет Workbox определить, что
нужно обновить кэш, сохраняя при этом предыдущие версии других
ресурсов.
Workbox автоматически удаляет устаревшие версии кэшей, если
используется precacheAndRoute. Однако для случаев отката к
предыдущей версии можно сохранять несколько версий ресурсов с разными
ревизиями и управлять ими через собственную логику:
const CURRENT_CACHE = 'my-app-cache-v3';
const PREVIOUS_CACHE = 'my-app-cache-v2';
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) =>
Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CURRENT_CACHE && cacheName !== PREVIOUS_CACHE) {
return caches.delete(cacheName);
}
})
)
)
);
});
Таким образом сохраняется возможность переключения между текущей и предыдущей версией приложения при необходимости.
Для случаев, когда новая версия приложения некорректно работает,
Workbox поддерживает стратегию staleWhileRevalidate или
ручной fallback на старую версию:
workbox.routing.registerRoute(
({request}) => request.destination === 'script',
new workbox.strategies.StaleWhileRevalidate({
cacheName: CURRENT_CACHE,
plugins: [
{
fetchDidFail: async ({originalRequest}) => {
const cache = await caches.open(PREVIOUS_CACHE);
const response = await cache.match(originalRequest);
return response || Response.error();
}
}
]
})
);
В этом примере при неудачном сетевом запросе Workbox автоматически пытается вернуть версию скрипта из предыдущего кэша, обеспечивая устойчивость приложения.
Для более сложных сценариев можно хранить версии ресурсов в
JSON-манифесте, который загружается через runtime caching.
Этот манифест содержит информацию о текущей и предыдущей стабильной
версии:
workbox.routing.registerRoute(
'/manifest.json',
async ({event}) => {
const response = await fetch(event.request);
const manifest = await response.json();
const cache = await caches.open(CURRENT_CACHE);
await cache.addAll(manifest.current);
return response;
}
);
Такой подход позволяет динамически управлять доступными версиями и откатом без необходимости пересборки Service Worker.
При обновлении ресурса, который критически важен для работы приложения, можно использовать Background Sync. Это гарантирует, что попытка обновления новой версии будет завершена, а в случае ошибки откат произойдет автоматически:
const bgSyncPlugin = new workbox.backgroundSync.BackgroundSyncPlugin('rollbackQueue', {
maxRetentionTime: 24 * 60 // минуты
});
workbox.routing.registerRoute(
/\/api\/critical-endpoint/,
new workbox.strategies.NetworkOnly({
plugins: [bgSyncPlugin]
}),
'POST'
);
Это обеспечивает надежное хранение запросов и возможность повторной попытки с предыдущей версии, если новая версия API недоступна.
revision для каждого
ресурса — это основа корректного управления версиями.fetchDidFail или
стратегии Workbox для безопасного восстановления работы
приложения.Такой подход обеспечивает контроль над версиями ресурсов, минимизирует риски некорректной работы после обновления и упрощает откат к стабильной версии приложения.