App Shell представляет собой минимальный набор статических ресурсов, необходимых для отображения пользовательского интерфейса веб-приложения. Обычно это HTML-шаблон, CSS-стили, JavaScript-файлы и базовые изображения. Основная цель App Shell — обеспечить мгновенную загрузку интерфейса и сделать веб-приложение похожим на нативное, даже при медленном соединении.
Кэширование App Shell позволяет загружать интерфейс практически мгновенно, независимо от состояния сети. Workbox предоставляет удобные механизмы для реализации такой стратегии через сервис-воркеры.
Для работы с Workbox сначала необходимо зарегистрировать сервис-воркер в основном JavaScript-файле приложения:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('Service Worker зарегистрирован', reg))
.catch(err => console.error('Ошибка регистрации Service Worker', err));
}
Файл sw.js станет точкой конфигурации кэширования App
Shell.
Workbox можно подключать как через CDN, так и через npm. Для CDN достаточно добавить в сервис-воркер:
importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.6.0/workbox-sw.js');
После этого объект workbox становится доступным для
конфигурации стратегий кэширования.
Cache First — оптимальная стратегия для App Shell, так как позволяет всегда быстро загружать интерфейс из кэша и обновлять ресурсы по мере необходимости в фоновом режиме.
Пример реализации с Workbox:
workbox.routing.registerRoute(
({request}) => request.destination === 'document' || request.destination === 'script' || request.destination === 'style',
new workbox.strategies.CacheFirst({
cacheName: 'app-shell-cache',
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 50,
maxAgeSeconds: 7 * 24 * 60 * 60, // 7 дней
}),
],
})
);
Ключевые моменты:
request.destination фильтрует типы ресурсов (HTML, JS,
CSS).cacheName задаёт отдельный кэш для App Shell.ExpirationPlugin управляет временем хранения и
количеством элементов в кэше.Workbox поддерживает precache, что позволяет кэшировать все ресурсы App Shell при установке сервис-воркера. Это гарантирует мгновенный доступ к интерфейсу при первой загрузке:
workbox.precaching.precacheAndRoute([
{ url: '/', revision: '1' },
{ url: '/index.html', revision: '1' },
{ url: '/styles/main.css', revision: '1' },
{ url: '/scripts/main.js', revision: '1' },
{ url: '/images/logo.png', revision: '1' },
]);
Особенности precache:
revision используется для контроля версий ресурсов. При
изменении файла сервис-воркер обновит кэш автоматически.Для поддержания актуальности интерфейса применяют стратегию stale-while-revalidate для некоторых ресурсов App Shell, позволяя сразу показывать старую версию, а новую загружать в фоне:
workbox.routing.registerRoute(
({request}) => request.destination === 'script' || request.destination === 'style',
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'app-shell-stale-cache',
})
);
Преимущества:
При изменении App Shell важно удалять устаревшие версии кэша. Workbox предоставляет плагины и API для этого:
self.addEventListener('activate', (event) => {
const currentCaches = ['app-shell-cache', 'app-shell-stale-cache'];
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (!currentCaches.includes(cacheName)) {
return caches.delete(cacheName);
}
})
);
})
);
});
Это предотвращает накопление старых версий ресурсов и уменьшает потребление памяти.
Все ресурсы App Shell, закэшированные через precache или Cache First, становятся доступными при отсутствии сети. Сервис-воркер перехватывает запросы и возвращает кэшированные файлы, обеспечивая работу интерфейса оффлайн:
self.addEventListener('fetch', (event) => {
// Workbox автоматически обрабатывает precache и routing
});
Благодаря этому приложение сохраняет отзывчивость даже при полной потере интернет-соединения.
revision для эффективного
обновления.ExpirationPlugin.Этот подход обеспечивает быстрый запуск приложения, минимизирует задержки при оффлайн-доступе и позволяет гибко управлять обновлениями App Shell.