Как превратить сайт в PWA: манифест и service worker
Практика3 минРедакция Innovialabs
Коротко
Чтобы сайт стал PWA, нужны три вещи: HTTPS, файл манифеста с названием и иконками и service worker, который кэширует ресурсы и отдаёт офлайн-страницу без сети.
Что нужно, чтобы сайт стал PWA
PWA (Progressive Web App) — это обычный сайт, который браузер может установить как приложение: с иконкой на рабочем столе, отдельным окном и работой без сети. Технически для этого нужны три составляющие:
- HTTPS — service worker работает только на защищённом соединении (исключение —
localhostпри разработке). - Web app manifest — JSON-файл с названием, иконками и параметрами запуска.
- Service worker — скрипт, который перехватывает сетевые запросы и управляет кэшем.
Дальше — каждый шаг по порядку.
Шаг 1. Манифест и иконки
Создайте файл manifest.webmanifest в корне сайта:
{
"name": "Мой сервис",
"short_name": "Сервис",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#7c3aed",
"icons": [
{ "src": "/icons/192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/512.png", "sizes": "512x512", "type": "image/png" },
{ "src": "/icons/maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
]
}
Подключите его в <head>:
<link rel="manifest" href="/manifest.webmanifest">
<meta name="theme-color" content="#7c3aed">
<link rel="apple-touch-icon" href="/icons/192.png">
Что важно:
- Иконки 192 и 512 px — минимальный набор для установки в Chrome.
- Maskable-иконка — с запасом полей, чтобы Android мог обрезать её в круг или скруглённый квадрат без потери логотипа.
- display: standalone — приложение открывается без адресной строки.
- start_url должен быть внутри области действия service worker.
Шаг 2. Регистрация service worker
Файл sw.js кладите в корень: область действия service worker по умолчанию ограничена папкой, где он лежит. Регистрация на странице:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js');
});
}
Регистрируйте после события load, чтобы не конкурировать с загрузкой основной страницы.
Шаг 3. Стратегии кэширования
Выбор стратегии зависит от типа ресурса:
| Стратегия | Как работает | Подходит для |
|---|---|---|
| Cache first | Сначала кэш, сеть — только если нет в кэше | Шрифты, иконки, файлы с хэшем в имени |
| Network first | Сначала сеть, кэш — если сети нет | HTML-страницы, данные, которые должны быть свежими |
| Stale-while-revalidate | Отдаёт кэш сразу и обновляет его в фоне | Аватары, некритичные API-ответы |
| Network only | Только сеть | Оплата, авторизация, POST-запросы |
Шаг 4. Офлайн-страница
Минимальный рабочий service worker: при установке кэшируем офлайн-страницу, для навигации используем network first с запасным вариантом.
const CACHE = 'app-v1';
const OFFLINE_URL = '/offline.html';
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE).then((cache) => cache.addAll([OFFLINE_URL]))
);
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) =>
Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)))
)
);
self.clients.claim();
});
self.addEventListener('fetch', (event) => {
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request).catch(() => caches.match(OFFLINE_URL))
);
}
});
Страница offline.html должна быть самодостаточной: стили — внутри файла, без внешних зависимостей.
Для крупных проектов удобнее не писать всё вручную, а использовать библиотеку Workbox — она реализует стратегии и версионирование кэша готовыми модулями.
Шаг 5. Проверка установки
- Откройте Chrome DevTools → вкладка Application: раздел Manifest покажет ошибки манифеста, раздел Service workers — статус воркера.
- В том же разделе можно включить режим Offline и проверить, что открывается офлайн-страница.
- Запустите аудит Lighthouse — он подсказывает, чего не хватает для PWA.
- Проверьте на реальном телефоне: Android и iOS ведут себя по-разному, на iOS установка делается через меню «Поделиться» → «На экран Домой».
Частые ошибки
- sw.js лежит в подпапке — воркер не контролирует остальные страницы.
- Нет версии кэша — пользователи годами видят старые файлы. Меняйте имя кэша при релизе и удаляйте старые в
activate. - Кэшируются HTML-страницы по cache first — новые версии сайта не доходят до пользователей.
- Кэшируются ответы с личными данными — на общем устройстве это утечка.
- Сам
sw.jsкэшируется сервером надолго — отдавайте его сCache-Control: no-cache.