Превращение в PWA
В этом модуле превратим наш чат в Progressive Web App — приложение, которое можно установить на главный экран и которое работает офлайн.
Перед началом: Модули 1–4. Инструменты: Vite PWA, Service Worker. Время: ~5 ч.
🔥 Инцидент. Пользователь в метро. Открывает чат — белый экран. Нет кэша, нет офлайн-страницы. Service Worker отсутствует. PWA даёт: установка на телефон, офлайн-доступ, push-уведомления. Но Vite PWA конфликтует с рядом плагинов — нужно аккуратно.
📖 Теория
Фокус: офлайн-first app shell. Service Worker кэширует shell, manifest делает приложение устанавливаемым.
Что такое PWA?
PWA — это веб-приложение, которое:
- Работает офлайн (Service Worker)
- Можно установить на устройство
- Получает push-уведомления
- Имеет нативный интерфейс
Установка Vite PWA Plugin
bashnpm install -D vite-plugin-pwa
Настройка vite.config.ts
typescriptimport { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import { VitePWA } from 'vite-plugin-pwa' export default defineConfig({ plugins: [ react(), VitePWA({ registerType: 'autoUpdate', manifest: { name: 'Serverless Chat', short_name: 'Chat', theme_color: '#ffffff', background_color: '#ffffff', display: 'standalone', icons: [ { src: 'icon-192.png', sizes: '192x192', type: 'image/png' }, { src: 'icon-512.png', sizes: '512x512', type: 'image/png' } ] }, // Важно: исключаем WebSocket из кэширования workbox: { navigateFallback: 'index.html', globIgnores: ['**/ws/**'], } }) ] })
Service Worker
Service Worker автоматически генерируется плагином, но вы можете настроить кастомную логику:
typescript// sw.ts (если использовать injectManifest: true) // Обработка входящего пуша self.addEventListener('push', (event) => { const data = event.data?.json() || { title: 'Новое сообщение', body: '' }; event.waitUntil( self.registration.showNotification(data.title, { body: data.body, icon: 'icon-192.png', badge: 'badge-72.png' }) ); });
PWA manifest
Файл manifest.json описывает приложение:
json{ "name": "Serverless Chat", "short_name": "Chat", "start_url": "/", "display": "standalone", "background_color": "#ffffff", "theme_color": "#2563eb", "icons": [ { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" } ] }
Проверка PWA
- Откройте Chrome DevTools → Application
- Проверьте:
- Manifest → отображается ли иконка и название
- Service Workers → зарегистрирован ли SW
- Lighthouse → пройдите аудит PWA
В следующем модуле добавим push-уведомления.
💱 Компромиссы (Trade-offs)
| Решение | Плюсы | Минусы |
|---|---|---|
vite-plugin-pwa (autoUpdate) | SW генерится автоматически, skipWaiting+clientsClaim | Конфликты с рядом плагинов Vite |
| Precache app shell | Офлайн сразу после установки SW | Большой precache → долгий первый заход |
navigateFallback: index.html | SPA-роутинг работает офлайн | 200 вместо 404 — битые ссылки не видны |
Manifest display: standalone | Нативный UX, установка на главный экран | Разные иконки/резолюции под платформы |
globIgnores: **/ws/** | WebSocket не кэшируется (как надо) | Легко забыть — WS ломается кэшем |
🧩 Проверь себя
registerType: 'autoUpdate' — поведение при новой сборке?🔗 Мостик к Модулю 6
PWA готов. Добавим push-уведомления.