Navigation Preload в сервис-воркерах позволяет сократить задержку при первоначальной загрузке страницы, когда браузер запрашивает основной HTML-документ. Этот механизм особенно полезен для сайтов с динамическим контентом и сложной логикой кэширования, где критично минимизировать время до первой отрисовки страницы.
Для активации Navigation Preload необходимо использовать объект
serviceWorkerRegistration.navigationPreload. Чаще всего
включение выполняется в событии activate:
self.addEventListener('activate', event => {
event.waitUntil(
self.registration.navigationPreload.enable()
);
});
После включения браузер будет параллельно отправлять запрос на сервер и активировать сервис-воркер, что позволяет комбинировать быстрый ответ сервера с кэшированными ресурсами.
В событии fetch можно получить предзагруженный запрос
через event.preloadResponse:
self.addEventListener('fetch', event => {
event.respondWith(
(async () => {
const preloadResponse = await event.preloadResponse;
if (preloadResponse) {
return preloadResponse;
}
return fetch(event.request);
})()
);
});
Этот подход обеспечивает минимальное время ожидания ответа для навигационных запросов.
Workbox предоставляет готовые стратегии кэширования, такие как
CacheFirst, NetworkFirst,
StaleWhileRevalidate, которые можно комбинировать с
Navigation Preload. Наиболее распространённый сценарий — использовать
Navigation Preload для NetworkFirst стратегии, чтобы
сократить время ответа при сетевых запросах.
import { registerRoute } from 'workbox-routing';
import { NetworkFirst } from 'workbox-strategies';
registerRoute(
({ request }) => request.mode === 'navigate',
new NetworkFirst({
cacheName: 'pages-cache',
plugins: [
{
fetchDidFail: async ({ request }) => {
console.log(`Network failed for ${request.url}`);
}
}
]
})
);
Чтобы интегрировать Navigation Preload с Workbox, нужно сначала включить preload в сервис-воркере, а затем внутри стратегии использовать его ответ как приоритетный:
self.addEventListener('fetch', event => {
if (event.request.mode === 'navigate') {
event.respondWith(
(async () => {
const preloadResponse = await event.preloadResponse;
if (preloadResponse) return preloadResponse;
const networkFirst = new NetworkFirst({
cacheName: 'pages-cache'
});
return networkFirst.handle({ request: event.request });
})()
);
}
});
NetworkFirst с Navigation Preload позволяет в случае
отсутствия сети отдать кэшированную версию страницы, минимизируя
зависимость от состояния соединения.navigate
запросов (HTML страниц), но не рекомендуется включать для всех ресурсов,
таких как CSS или JS, так как это увеличивает нагрузку на сеть.NetworkFirst подходит для динамических
страниц, где важно иметь актуальный контент, а CacheFirst
лучше использовать для статических ресурсов.if ('navigationPreload' in self.registration) {
self.registration.navigationPreload.enable();
}
fetch и сначала проверяет
preloadResponse.preloadResponse доступен, возвращается этот
ответ.NetworkFirst, CacheFirst и др.).Такое сочетание обеспечивает баланс между скоростью загрузки, надежностью кэширования и свежестью данных, что критично для современных Progressive Web Apps.