Перейти к содержанию
Innovialabs

Как превратить сайт в PWA: манифест и service worker

Практика3 мин

Коротко

Чтобы сайт стал 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.

Частые вопросы

Полноценная офлайн-работа не обязательна, но хотя бы офлайн-страница заметно улучшает опыт: пользователь видит понятное сообщение вместо ошибки браузера.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

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

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.