При загрузке сайта каждый лишний запрос к серверу увеличивает LCP. Без SW ресурсы загружаются из сети при каждом переходе, что особенно критично для мобильных пользователей с нестабильным соединением. Мы решаем эту проблему, внедряя фоновый скрипт, перехватывающий запросы. Правильная конфигурация стратегий позволяет сократить LCP на 40–60%, а TTFB — в 3–5 раз. Наш опыт показывает, что грамотная настройка Service Worker повышает конверсию на 10–20% и снижает нагрузку на сервер вдвое.
Недавний кейс из нашей практики: интернет-магазин на Next.js имел LCP 4.2 с вместо нормы 2.5 с. После настройки SW со стратегией Network First для страниц и Cache First для статики LCP упал до 1.8 с, конверсия выросла на 15%. За 6 лет работы мы реализовали более 80 проектов с PWA, гарантируя улучшение Core Web Vitals минимум на 30%.
В этой статье разберём, как реализовать кэширование правильно, чтобы пользователи получали контент мгновенно даже при обрыве сети. Вы узнаете, какие стратегии выбрать для разных типов ресурсов и как избежать типичных ошибок.
Какие проблемы решает Service Worker
Service Worker устраняет несколько типовых узких мест:
- Медленная загрузка повторных посещений: без кэша все ресурсы запрашиваются заново. SW возвращает их из кэша мгновенно.
- Отсутствие офлайн-доступа: при обрыве сети пользователь видит пустую страницу. SW может показывать кэшированную версию.
- Высокий TTFB: если API-запросы не кэшируются, каждый рендер страницы ждёт ответа сервера. SW может отвечать из кэша, обновляя данные в фоне.
- Hydration mismatch: при SSR несоответствие между серверным и клиентским HTML. Кэширование статики уменьшает время гидратации.
Стратегии кэширования: сравнение
Основные стратегии: Cache First, Network First, Stale While Revalidate. Выбор стратегии зависит от типа ресурса и требуемой свежести.
| Стратегия | Применение | Время загрузки (в идеале) | Изменчивость ресурса | Риск устаревания |
|---|---|---|---|---|
| Cache First | Статика (CSS, JS, шрифты) | 0-50 мс (из кэша) | Нет | Низкий, если версионировать файлы |
| Network First | HTML-страницы, API | 200-500 мс (сеть) или 0 (офлайн) | Средняя | Низкий, кэш обновляется после каждого успеха |
| Stale While Revalidate | Изображения, товары | 0 (кэш) + 100 мс (фон) | Низкая | Умеренный, выдача устаревшего до обновления |
Cache First обеспечивает загрузку из кэша в 10 раз быстрее, чем Network First, для статики. Первая стратегия подходит для неизменяемых файлов, вторая — для страниц, которые должны быть всегда свежими, третья — для ресурсов, где можно показать устаревшую версию на 1–2 секунды.
Как мы это делаем: кейс внедрения
Работаем с React, Next.js, Vite. Для production используем библиотеку Workbox — она избавляет от ручного кэширования и даёт готовые обработчики. Пример настройки с vite-plugin-pwa:
// vite.config.ts
import { defineConfig } from 'vite';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({
plugins: [
VitePWA({
registerType: 'autoUpdate',
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
runtimeCaching: [
{
urlPattern: /^https:\/\/api\.example\.ru/,
handler: 'NetworkFirst',
options: {
cacheName: 'api-cache',
networkTimeoutSeconds: 3,
expiration: {
maxEntries: 50,
maxAgeSeconds: 300,
},
},
},
{
urlPattern: /\.(?:webp|avif|jpg|png|svg)$/,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'images-cache',
expiration: {
maxEntries: 200,
maxAgeSeconds: 30 * 24 * 60 * 60,
},
},
},
],
},
}),
],
});
Пример регистрации
// src/service-worker-registration.ts
export function registerServiceWorker() {
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js', { scope: '/' })
.then(registration => {
console.log('SW registered:', registration.scope);
setInterval(() => registration.update(), 60 * 60 * 1000);
})
.catch(err => console.error('SW registration failed:', err));
});
}
}
Почему важно кэшировать API-запросы?
API-запросы — частая причина высокого TTFB. Если не кэшировать ответы, каждый переход на страницу вызовет новый запрос. Стратегия Network First с коротким временем жизни кэша (например, 5 минут) ускоряет повторные просмотры. В случае неудачи сети пользователь получит хотя бы кэшированные данные, а не ошибку. Время ответа API может достигать 500 мс, а кэширование сокращает его до 0–50 мс.
Как обновлять кэш без потери пользователей?
При обновлении Service Worker важно корректно управлять версиями кэша. В activate-событии мы удаляем старые кэши, оставляя только актуальный. Для уведомления пользователя о новом SW используем событие updatefound и показываем кнопку «Обновить»:
navigator.serviceWorker.ready.then(registration => {
registration.addEventListener('updatefound', () => {
const newWorker = registration.installing!;
newWorker.addEventListener('statechange', () => {
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
showUpdateNotification(() => {
newWorker.postMessage({ type: 'SKIP_WAITING' });
window.location.reload();
});
}
});
});
});
Процесс работы
- Аналитика: аудит текущих Core Web Vitals, определение узких мест (LCP, CLS).
- Проектирование: выбор стратегий для каждой группы ресурсов, определение scope.
- Реализация: написание Service Worker (вручную или через Workbox), интеграция с билд-системой.
- Тестирование: проверка в Chrome DevTools (Application > Service Workers), Lighthouse, WebPageTest.
- Деплой: поэтапный rollout, мониторинг ошибок.
Сроки ориентировочно
Базовая настройка — от 1 до 2 дней. Если требуется кастомная логика (например, кэширование GraphQL), срок увеличивается до 4-5 дней. Стоимость рассчитывается индивидуально — свяжитесь с нами для оценки.
Что входит в работу
- Конфигурация Service Worker со стратегиями для статики, страниц и API.
- Настройка Workbox (если используется Vite/Webpack).
- Реализация уведомления об обновлении.
- Создание офлайн-страницы.
- Тестирование и профилирование.
- Документация по стратегиям и эксплуатации.
- Пост-релизная поддержка (2 недели).
Типичные ошибки при внедрении Service Worker
| Ошибка | Последствие | Решение |
|---|---|---|
| Неправильный scope | Service Worker не перехватывает запросы | Указывайте scope: '/' |
| Отсутствие очистки старых кэшей | Накопление версий, лишний трафик | Удаляйте старые кэши в activate |
| Кэширование без версионирования | Пользователь видит устаревшие данные | Используйте Network First или короткий срок жизни |
Свяжитесь с нами для консультации по вашему проекту. Закажите внедрение Service Worker для улучшения Core Web Vitals.







