Progressive Web App: Service Worker, офлайн, Web Push, Add to Home Screen
PWA — это не отдельная технология, это набор браузерных API, которые вместе делают веб-приложение ближе к нативному. Можно реализовать все три компонента (Service Worker, Web App Manifest, HTTPS), но получить плохое PWA. Можно сделать только офлайн-кэширование и Web Push — и это уже даст ощутимую ценность для пользователей.
Service Worker: как это реально работает
Service Worker — это JavaScript-прокси между браузером и сетью. Работает в отдельном потоке, нет доступа к DOM, живёт независимо от страницы. Основная задача — перехватывать сетевые запросы и решать, откуда их отдавать: из кэша, из сети, или комбинация.
Стратегии кэширования для разных ресурсов:
Cache First — сначала кэш, потом сеть. Для статических ассетов с content hash в имени (скрипты, стили, шрифты): файл с хешем не изменится никогда, можно кэшировать вечно.
Network First — сначала сеть, при ошибке — кэш. Для API-запросов, которые должны возвращать актуальные данные, но при офлайне лучше показать устаревшие чем ничего.
Stale While Revalidate — отдаём из кэша немедленно, одновременно обновляем кэш из сети. Для контента, где небольшая задержка актуализации допустима: страницы статей, каталог товаров.
Workbox от Google берёт на себя рутинную логику: версионирование кэша, очистка старых записей, стратегии. Без Workbox написать корректный Service Worker с правильной инвалидацией кэша — 300+ строк кода с нетривиальными edge cases.
Vite + vite-plugin-pwa генерирует Service Worker автоматически из конфига, включая precaching всех статических ассетов после сборки.
Офлайн-режим: какой он на самом деле
«Работает офлайн» для разных продуктов означает разное.
Офлайн-чтение: новостные сайты, документация, блоги. Service Worker кэширует страницы при первом посещении. Стратегия Stale While Revalidate + Background Sync для синхронизации когда соединение восстанавливается.
Офлайн-редактирование: задачи, заметки, формы. IndexedDB хранит несохранённые данные локально. Background Sync API ставит операцию в очередь — браузер сам синхронизирует когда соединение появится, даже если вкладка закрыта. Ограничение: Background Sync поддерживается только в Chromium, в Safari — нет.
Офлайн-форма: пользователь заполнил форму офлайн, нажал отправить. Без PWA — ошибка, данные потеряны. С Background Sync — форма ставится в очередь, отправляется автоматически. Для медицинских и страховых форм это критически важно.
Проблема, о которой часто забывают: конфликты при синхронизации. Пользователь А редактировал запись офлайн, пользователь Б изменил её онлайн. При синхронизации — конфликт. Нужна стратегия разрешения: last-write-wins (опасно), three-way merge (сложно), или показ конфликта пользователю (честно).
Web Push: доставка уведомлений
Web Push работает через браузер + Push Service (отдельный для каждого браузера: FCM для Chrome/Edge, APNs для Safari). Пользователь даёт разрешение → браузер подписывается на Push Service → вы получаете endpoint + ключи → отправляете сообщение на Push Service → он доставляет в браузер.
Реализация: библиотека web-push (Node.js) или аналог для вашего бэкенда. VAPID-ключи генерируются один раз. Подписка хранится в базе данных — это ваш «токен» устройства.
Ограничения по платформам в 2024:
- iOS 16.4+ поддерживает Web Push, но только для установленных PWA (добавленных на домашний экран)
- Chrome, Firefox, Edge — полная поддержка в браузере без установки
- Safari macOS — поддержка с macOS Ventura
Частота отправки и релевантность уведомлений напрямую влияют на отток подписчиков. Пользователи отзывают разрешение, если уведомления нерелевантны. A/B тестирование времени отправки и формулировок — стандартная практика.
Add to Home Screen и установка
Web App Manifest — JSON-файл с метаданными приложения: name, short_name, icons (минимум 192x192 и 512x512 PNG), start_url, display: standalone, theme_color, background_color.
display: standalone скрывает браузерный UI — приложение выглядит как нативное. display: minimal-ui оставляет минимальную навигацию браузера.
Браузер показывает Install Prompt (beforeinstallprompt) при выполнении условий: HTTPS, валидный манифест, Service Worker. Prompt можно отложить и показать в нужный момент (не сразу при загрузке):
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
});
// Позже, по действию пользователя:
installButton.addEventListener('click', async () => {
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
});
После установки отслеживайте через appinstalled событие и display-mode: standalone медиа-запрос.
Производительность и PWA
App Shell архитектура: минимальный HTML/CSS/JS, необходимый для рендера оболочки приложения, кэшируется Service Worker и загружается мгновенно. Контент загружается поверх. Разница в восприятии скорости — ощутима даже при медленном соединении.
Precaching критических ресурсов при установке Service Worker: при первом визите кэшируем всё необходимое для работы офлайн. Размер precache бандла влияет на время первой установки — не кладите туда всё подряд.
Процесс работы
Аудит текущего приложения (Lighthouse PWA score), определение ценных офлайн-сценариев, настройка Service Worker через Workbox, реализация Web Push если нужно, тестирование на реальных устройствах. Lighthouse PWA раздел и Chrome DevTools Application tab — основные инструменты отладки.
Сроки
Базовая PWA (манифест + Service Worker + офлайн-кэш статики): 1–2 недели поверх готового приложения. Web Push интеграция: 1–2 недели. Офлайн-редактирование с IndexedDB + Background Sync: 3–6 недель в зависимости от сложности данных.







