PWA & Service Workers concept page: Service Worker as browser proxy for network requests, cache strategies (cache-first, network-first, stale-while-revalidate), Workbox library, manifest.json (installable), Push API + Notifications, Background Sync queue, offline-first patterns, PWA vs native trade-offs ADR. Four scenarios: SW intercepts fetch and chooses cache strategy, offline page when network down, push notification flow (tab closed), background sync queue.
Progressive Web App нужен там, где веб-приложение должно вести себя ближе к нативному: открываться с home screen, быстро стартовать после первого визита, переживать плохую сеть, показывать offline fallback, принимать push notifications и откладывать действия до восстановления соединения. Это особенно важно для мобильной аудитории, регионов с дорогим трафиком, внутренних инструментов в полях, delivery, commerce, education и медиа.
Service Worker - центральный механизм PWA. Это отдельный JavaScript worker, который живет между страницей и сетью, перехватывает fetch, управляет Cache API, может проснуться на push event или background sync и не зависит от конкретной открытой вкладки. Без него manifest дает только install-like обертку; с ним сайт получает control plane для сетевых стратегий.
Знать PWA важно и для системного дизайна frontend. Вы начинаете думать не "браузер сделал запрос и ждет", а "есть shell, cache, runtime data, outbox, retry, stale data, push subscription, lifecycle update". Такой подход помогает даже без полной PWA-установки: stale-while-revalidate, offline banners, idempotent mutations и cache invalidation полезны обычным веб-приложениям.
Service Worker - это programmable proxy внутри origin. Page делает запрос, но request сначала попадает в SW. Worker решает: вернуть precached app shell, пойти в network, отдать stale cache и обновить в фоне, показать offline page, положить mutation в IndexedDB outbox или пропустить request как есть. Он не имеет прямого доступа к DOM, поэтому общается со страницами через postMessage, Cache API, IndexedDB и события браузера.
PWA состоит из нескольких стандартов: Web App Manifest, HTTPS, responsive UI, Service Worker, Cache API, Push API, Notifications API, иногда Background Sync и Web Share. App Shell pattern разделяет статичный каркас приложения и динамические данные. Shell кешируется заранее, данные грузятся отдельно и могут иметь разные стратегии.
Главное ограничение: Service Worker - не вечный backend в браузере. Он запускается браузером по событию, выполняет работу и может быть остановлен. Поэтому состояние надо хранить явно в Cache API или IndexedDB, а не в глобальных переменных worker.
Диаграмма показывает PWA как сетевой слой вокруг обычной страницы. В браузере есть page, Service Worker, Cache API, IndexedDB, notification tray и набор стратегий: cache-first, network-first, stale-while-revalidate. Во внешнем мире есть CDN, API, push service вроде FCM/APNs и backend push server с VAPID-ключами.
Такой рисунок полезен, потому что отделяет разные классы данных. Статика и app shell обычно идут через cache-first или precache. API-данные чаще идут network-first с fallback на cache или stale-while-revalidate. Изображения могут идти через CDN и runtime cache. POST-mutations нельзя просто кешировать как GET; для них нужен outbox, idempotency key и явный статус для пользователя.
Диаграмма также показывает, что push идет не напрямую от API к вкладке. Backend отправляет VAPID-signed payload в push service, браузер будит Service Worker, а worker уже вызывает showNotification. Поэтому push работает даже при закрытой вкладке, но имеет лимиты размера payload, permission UX и разные ограничения браузеров.
Первый сценарий: Service Worker перехватывает fetch и выбирает стратегию. /index.html, JS, CSS и icons можно precache-ить, чтобы второй запуск был мгновенным. Для /api/articles лучше network-first: сначала свежие данные, при сбое - cached response с badge "offline" или "stale". Для картинок часто подходит stale-while-revalidate: быстро показать старую версию и обновить cache в фоне. Урок: одна стратегия для всего origin почти всегда неправильна.
Второй сценарий: offline fallback. Пользователь открывает PWA в метро без сети. Вместо browser error Service Worker возвращает cached app shell, затем cached content или branded offline page. Если пользователь отправляет комментарий offline, хороший PWA не просто показывает error, а сохраняет action в IndexedDB outbox и явно сообщает, что действие будет отправлено при восстановлении сети. Связанная тема: ::concept{slug="offline-first"}.
Третий сценарий: push notification. Пользователь дает permission, page получает subscription через pushManager.subscribe, отправляет endpoint и keys на backend. Позже backend отправляет уведомление через FCM/APNs, браузер будит Service Worker, SW показывает OS notification, click открывает нужный deep link. Урок: push - это re-engagement канал, но он требует бережного UX, opt-in и строгой полезности. Спам быстро приводит к блокировке permissions.
Четвертый сценарий: background sync queue. Offline POST сохраняется в IndexedDB, регистрируется sync event, браузер пытается отправить queue после восстановления сети. Но Background Sync - best effort: Safari не поддерживает его как Chrome, браузер может ограничить wakeups, устройство может экономить батарею. Поэтому critical flows должны иметь видимый queue state, manual retry и backend idempotency.
PWA vs native app. PWA выигрывает скоростью распространения: ссылка вместо app store, instant updates, единая web codebase, ниже friction. Проигрывает в части platform APIs, background execution, deep OS integration, store discovery и некоторых iOS-ограничениях. Для commerce, content, dashboards, messaging-lite и internal tools PWA часто достаточно. Для heavy bluetooth, advanced background tracking, низкоуровневых sensors или строгих app-store каналов native может быть необходим.
Cache-first vs network-first. Cache-first дает скорость и offline, но рискует устаревшим контентом. Он подходит для versioned assets: /app.abc123.js, icons, fonts, shell. Network-first дает свежесть, но может зависнуть на плохой сети; всегда нужны timeout и fallback. Он подходит для user-specific API. Stale-while-revalidate хорош для read-heavy data, где старые данные лучше пустого экрана: статьи, профили, feed cards, metadata. Но SWR требует аккуратного UI: пользователь должен понимать, когда данные обновились или стали stale.
skipWaiting() и clients.claim() ускоряют rollout нового Service Worker, но могут сломать открытые вкладки, если новая версия assets несовместима со старым HTML. Более безопасный подход для сложных приложений - показывать "New version available" и обновлять после согласия или при следующем запуске. Для security hotfix можно активировать сразу, но это осознанный риск.
Workbox vs handwritten SW. Workbox снижает вероятность ошибок в cache expiration, routing, precache manifest и strategies. Самописный worker полезен для обучения или очень специфичного контроля, но в production часто превращается в набор забытых edge cases: opaque responses, cache version cleanup, navigation preload, range requests, quota eviction, offline analytics. Практичный выбор: Workbox для стандартных стратегий, свой код только для outbox, domain-specific fallback и messaging.
Push notifications имеют продуктовый trade-off. Они повышают engagement, но требуют permission prompt, subscription storage, unsubscribe flow, rate limits и content policy. Permission надо спрашивать после явного действия, а не на первом экране. Payload лучше держать маленьким и приватным: не класть чувствительные данные в notification body, если устройство может быть заблокировано на общем экране.
Twitter Lite показал, что PWA может снизить вес приложения и улучшить доступ на слабой сети. Starbucks использовал offline ordering-like UX и быстрый shell для мобильных клиентов. Pinterest и Tinder публично рассказывали о росте engagement после PWA-оптимизаций. Spotify Web, IDE-like tools и documentation sites используют service worker cache для быстрого повторного старта.
В enterprise PWA полезен для field workers: инвентаризация, формы инспекции, POS-lite, delivery dashboards. Там сеть часто непредсказуема, а действие должно сохраняться локально. Но архитектура должна включать sync semantics: idempotency keys, retry policies, конфликтные состояния, stale indicators и серверную валидацию.
Для CloudArch тема связана с ::concept{slug="offline-first"}, ::concept{slug="web-perf-core-vitals"} и ::concept{slug="server-sent-events"}. Service Worker улучшает повторный запуск и offline-read, но realtime updates лучше решать отдельным транспортом: WebSocket, SSE или polling. PWA не заменяет sync engine, а дает браузерные примитивы для cache, install и background behavior.
Кешировать все GET одинаково - ошибка. HTML, versioned JS, API JSON, avatars и private documents имеют разные lifetime и privacy. Кешировать authenticated responses без учета пользователя опасно на shared devices. Неочищенные cache versions приводят к quota pressure и странным багам после релизов.
cache.addAll в install без fallback может сорвать установку SW из-за одного 404 asset. Отсутствие offline navigation fallback возвращает стандартную browser error page. Отсутствие timeout у network-first делает UX хуже offline: пользователь ждет долгий TCP timeout вместо мгновенного stale response.
Еще частые ошибки: показывать permission prompt для notifications при первом заходе; не давать unsubscribe; считать Background Sync гарантированным; отправлять POST повторно без idempotency key; хранить outbox только в памяти; не показывать пользователю pending state; ломать приложение при обновлении SW; забывать, что iOS push работает только для installed PWA начиная с iOS 16.4 и с ограничениями.
Не надо делать PWA ради бейджа Lighthouse, если продукту не нужны install, offline, push или быстрый repeat launch. Service Worker добавляет дополнительный слой кеширования и может усложнить debugging. Для простого marketing site обычно достаточно HTTP caching, CDN и responsive HTML.
Не стоит включать aggressive offline для данных, где stale state опасен: trading, medical orders, payment confirmation, seat reservation, inventory decrement. Там можно кешировать shell, но критические операции должны требовать свежего server confirmation и понятного состояния.
Не надо использовать push как замену email или in-app inbox без продуктовой причины. Если уведомления не срочные и не ожидаемые, они ухудшают доверие и ведут к deny permission. Не надо полагаться на background execution для SLA: браузер может не разбудить worker вовремя.
Изучите MDN по Service Worker, Cache API, Push API, Notifications API и Web App Manifest. Для production-паттернов полезны Workbox docs, web.dev PWA guides и Jake Archibald articles про offline cookbook. Внутри курса продолжайте через ::concept{slug="offline-first"}, чтобы понять outbox, local database и конфликтные merge strategies, и через ::concept{slug="web-perf-core-vitals"}, чтобы связать PWA cache с LCP, CLS и perceived performance.