04 / Журнал DAMIR STUDIO

PWA: как заменить мобильное приложение сайтом

Прогрессивные веб-приложения стирают границу между сайтом и нативным приложением. Разбираем архитектуру, кейсы и экономию для B2B-проектов.

Все статьи
PWA: как заменить мобильное приложение сайтомDAMIR STUDIO / Журнал

Почему PWA — это не тренд, а архитектурный выбор

Progressive Web App — это веб-приложение, которое устанавливается на устройство пользователя, работает офлайн, получает push-уведомления и не требует App Store или Google Play. Для B2B-компаний это означает: один кодбейс, одна команда, один релизный цикл вместо двух мобильных платформ.

Современные PWA закрывают 90-95% задач, которые раньше требовали нативной разработки. Оставшиеся 5-10% — это специфичные функции вроде Bluetooth Low Energy, ARKit или фоновых геолокационных сервисов, которые постепенно также становятся доступными через Web API.

Архитектура PWA: что под капотом

Service Worker

Service Worker — это JavaScript-файл, который браузер запускает в фоновом режиме, отдельно от страницы. Он перехватывает сетевые запросы, управляет кэшем и обеспечивает офлайн-работу. Это ядро любого PWA.

Базовый пример регистрации Service Worker:

main.js:

  • if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js').then(reg => console.log('SW registered:', reg.scope)).catch(err => console.error('SW registration failed:', err)); }

sw.js с стратегей Cache-First:

  • const CACHE_NAME = 'app-v1'; const ASSETS = ['/', '/index.html', '/styles.css', '/app.js', '/offline.html'];
  • self.addEventListener('install', e => { e.waitUntil(caches.open(CACHE_NAME).then(cache => cache.addAll(ASSETS))); });
  • self.addEventListener('fetch', e => { e.respondWith(caches.match(e.request).then(response => response || fetch(e.request))); });

Эта схема кэширует ключевые ресурсы при установке и отдаёт их из кэша при каждом запросе. Если ресурса нет в кэше — запрос идёт в сеть. Для B2B-приложений с нестабильным соединением это критично.

Web App Manifest

Manifest — это JSON-файл, который описывает, как PWA выглядит на домашнем экране: иконки, название, тему, ориентацию, режим запуска. Без него браузер не предложит установку.

Пример manifest.json:

  • { "name": "DAMIR Studio CRM", "short_name": "DAMIR CRM", "start_url": "/", "display": "standalone", "background_color": "#0a0a0a", "theme_color": "#00ff88", "icons": [{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }] } }

Параметр display: standalone убирает адресную строку браузера — приложение выглядит как нативное. Параметр purpose: any maskable обеспечивает корректное отображение иконки на Android.

HTTPS — обязательное условие

Service Workers работают только по HTTPS. Исключение — localhost для разработки. Если ваш сайт на HTTP, PWA не активируется. Это не рекомендация, это жёсткое ограничение безопасности.

Когда PWA выгоднее нативного приложения

Рассмотрим реальный B2B-кейс: внутренний CRM для менеджеров по продажам, которые работают в полях. Нативное приложение потребует:

  • iOS-разработчика (Swift/Objective-C) — от 250 000 руб./мес
  • Android-разработчика (Kotlin/Java) — от 250 000 руб./мес
  • Согласование в App Store (1-7 дней на ревью) и Google Play (1-3 дня)
  • Раздельные релизные циклы и багфиксы для каждой платформы
  • Отдельный бэкенд-API или адаптация существующего

PWA на базе существующего веб-проекта потребует:

  • Добавления Service Worker — 1-2 дня разработчика
  • Создания manifest.json и иконок — 0.5 дня
  • Настройки push-уведомлений через Web Push API — 2-3 дня
  • Тестирования офлайн-режима и установки — 1-2 дня

Итог: функциональный PWA для B2B-сценария запускается за 5-8 дней силами одного фронтенд-разработчика вместо 3-6 месяцев команды из двух мобильных разработчиков.

Стратегии кэширования для B2B-приложений

Cache-First для статики

CSS, JS, шрифты и изображения кэшируются при первой загрузке. Все последующие обращения идут из кэша мгновенно. Обновление происходит при изменении версии Service Worker.

Network-First для данных

API-запросы сначала идут в сеть. Если сети нет — отдаётся кэшированный ответ. Для CRM это означает, что менеджер видит последние данные при наличии интернета и актуальный кэш при его отсутствии.

Пример Network-First:

  • self.addEventListener('fetch', e => { if (e.request.url.includes('/api/')) { e.respondWith(fetch(e.request).catch(() => caches.match(e.request))); } });

Stale-While-Revalidate

Отдаёт кэшированный ответ немедленно, параллельно делает сетевой запрос и обновляет кэш. Баланс между скоростью и актуальностью — идеален для новостных лент и дашбордов.

Push-уведомления в PWA

Web Push API позволяет отправлять уведомления пользователю даже когда приложение закрыто. Для B2B это значит: напоминания о задачах, уведомления о новых лидах, алерты о статусах заказов — всё без установки нативного приложения.

Подписка на push-уведомления:

  • async function subscribeToPush() { const reg = await navigator.serviceWorker.ready; const subscription = await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY) }); await sendSubscriptionToServer(subscription); }

На сервере используется VAPID-ключи для аутентификации и библиотеки вроде web-push для Node.js. Отправка уведомления занимает одну строку: webpush.sendNotification(subscription, JSON.stringify({ title: 'Новый лид', body: 'Заявка от ООО Ромашка' })).

Ограничения PWA в 2026 году

Несмотря на зрелость технологии, ограничения остаются:

  • iOS: фоновые процессы ограничены 30 секундами, push-уведомления работают только на iOS 16.4+
  • Нет прямого доступа к контактам, календарю и файловой системе вне sandbox
  • Bluetooth и NFC — частичная поддержка через Web Bluetooth и Web NFC
  • App Store и Google Play недоступны как каналы дистрибуции
  • Ограниченный доступ к нативным SDK для AR и VR

Для большинства B2B-сценариев — CRM, дашборды, формы, каталоги, бронирования — этих ограничений не существует. PWA полностью покрывает потребности.

Метрики производительности PWA

PWA не освобождает от ответственности за производительность. Ключевые метрики для отслеживания:

  • Core Web Vitals: LCP (Largest Contentful Paint) < 2.5 с, FID < 100 мс, CLS < 0.1
  • Time to Interactive — время до интерактивности интерфейса
  • Cache hit rate — доля запросов, отдающихся из кэша Service Worker
  • Install conversion rate — процент пользователей, установивших PWA
  • Offline usage rate — доля сессий в офлайн-режиме

Измеряйте через Lighthouse, Chrome DevTools Application-вкладку и пользовательскую аналитику. Lighthouse Audit для PWA проверяет: installable, works offline, splash screen, themed — четыре критерия, без которых PWA не считается полноценным.

Практический чеклист запуска PWA

Пошаговый план для конвертации существующего веб-проекта в PWA:

  • 1. Настройте HTTPS на продакшене — без него ничего не заработает
  • 2. Создайте manifest.json с иконками 192px и 512px, display: standalone
  • 3. Добавьте ссылку на manifest в HTML: link rel=manifest href=/manifest.json
  • 4. Напишите Service Worker с Cache-First для статики и Network-First для API
  • 5. Зарегистрируйте Service Worker при загрузке страницы
  • 6. Создайте offline.html — fallback-страницу для отсутствующего кэша
  • 7. Сгенерируйте VAPID-ключи и настройте push-уведомления
  • 8. Прогоните Lighthouse Audit и добейтесь PWA-скоринга 90+
  • 9. Протестируйте установку на iOS и Android, офлайн-режим и push
  • 10. Добавьте кнопку Установить приложение в интерфейс через beforeinstallprompt event

Заключение

PWA — это архитектурное решение, а не компромисс. Для B2B-продуктов, где скорость доставки и единый кодбейс важнее доступа к специфичным API платформы, Progressive Web Apps сокращают время разработки в 3-5 раз, а стоимость владения — в 2-3 раза. Один разработчик, один репозиторий, мгновенные обновления без ревью сторов — это стандарт для современной разработки клиентских приложений.

Превратим идею
в рабочую систему

Обсудить проект