Манифест PWA — это JSON-файл, в котором описано приложение: как оно называется, какие у него иконки и в каком виде открывается окно. Сервис-воркер — JavaScript-скрипт, который браузер держит отдельно от страниц и который перехватывает сетевые запросы, поэтому именно он отвечает за офлайн-режим, кеш и пуш-уведомления. По отдельности ни один из них не делает сайт устанавливаемым: браузер считает PWA готовым к установке, когда есть и корректный манифест с иконками, и зарегистрированный сервис-воркер, отданный по HTTPS. Дальше — по полям манифеста, иконкам, жизненному циклу воркера и ошибкам, из-за которых установка молча не срабатывает.
Манифест PWA: что это и как работает manifest.json
Манифест — обычный текстовый файл, чаще всего manifest.json, лежащий на том же домене, что и сайт. Подключается одной строкой в <head>: <link rel="manifest" href="/manifest.json">. Отдавать его нужно с типом application/manifest+json (браузеры принимают и application/json, но первый вариант правильный) и без редиректов на другой домен — манифест с чужого origin браузер проигнорирует.
Читает его браузер до первой отрисовки окна. Отсюда заставка при запуске установленного приложения: пока грузится страница, браузер рисует экран из background_color и иконки из icons. Если манифест битый или не подгрузился, приложение всё равно откроется — просто как обычная вкладка, без заставки, без правильного имени и без предложения установки.
Проверить, что файл реально прочитан, можно в DevTools: вкладка Application → Manifest. Там видны распознанные поля, превью иконок и предупреждения об ошибках. Пустая панель означает, что манифест не найден, не распарсился или заблокирован политикой безопасности.
name и short_name
name — полное название приложения: показывается в диалоге установки, в списке приложений и в заголовке окна в режиме standalone. short_name — короткая подпись под иконкой на домашнем экране; если его не указать, система возьмёт name и обрежет многоточием.
Практическое правило: name пишите так, как продукт называется в рекламе и в интерфейсе, а short_name — одним-двумя словами без хвостов вроде «— официальный сайт». Обрезка подписи выглядит неряшливо, а на узких экранах места под иконкой мало. Латиницу и кириллицу лучше не смешивать в одном названии: системные шрифты на разных устройствах отрисуют смесь по-разному.
start_url и scope
start_url — адрес, с которого стартует установленное приложение. scope — граница, внутри которой ссылки считаются «своими» и открываются в окне приложения, а не в браузере.
Здесь самая частая тихая поломка: если scope не указан, браузер вычисляет его от start_url, отрезая последний сегмент пути. Манифест с start_url: "/app/index.html" и без scope даст зону /app/, и всё, что лежит выше — например, раздел с личным кабинетом или лендинг акции, — будет выпадать в браузер. Поэтому scope прописывают явно: обычно "/", если приложение занимает весь домен, или конкретную папку, если PWA живёт рядом с обычным сайтом.
Второй нюанс: start_url должен попадать внутрь scope. Если он вне зоны, браузер может отказаться считать приложение устанавливаемым. Третий: в start_url часто добавляют параметр для аналитики, чтобы отделять запуски из установленного приложения от обычных визитов. Практика рабочая, но параметр должен быть статичным — динамическую подстановку манифест не поддерживает.
display: browser, standalone, fullscreen
display определяет, сколько интерфейса браузера увидит пользователь.
| Значение | Что видит пользователь | Когда выбирать |
|---|---|---|
browser | Обычная вкладка с адресной строкой и панелью | Витрины, лендинги, контент, куда приходят из поиска |
standalone | Отдельное окно без адресной строки, но со статус-баром системы | Основной режим для PWA: сервисы, кабинеты, приложения-утилиты |
fullscreen | Окно без системных элементов, занимает весь экран | Игры, плееры, иммерсивные сценарии |
minimal-ui | Минимальный набор навигации | Формально есть в спецификации, поддержка в браузерах нестабильна |
Для большинства проектов правильный ответ — standalone: нет адресной строки, своя иконка в списке задач, но системный статус-бар с часами, зарядом и уведомлениями остаётся — пользователь не чувствует, что попал в ловушку. browser имеет смысл как осознанный выбор для контентных страниц: вы не притворяетесь приложением, зато сохраняете все возможности вкладки. fullscreen берите только если внутри действительно полноэкранный опыт; в остальных случаях пользователь не поймёт, как выйти.
Есть ещё display_override — массив предпочтений, который браузер перебирает по порядку и берёт первое поддерживаемое. Удобно, когда хочется standalone, но с запасным вариантом.
background_color и theme_color
background_color — цвет заставки, которая показывается в момент запуска, пока не отрисовался первый экран. Он должен совпадать с фоном самого приложения, иначе получится вспышка чужого цвета между заставкой и интерфейсом.
theme_color — цвет системной панели: строки состояния на Android, оформления окна в некоторых браузерах и на десктопе. Он задаёт рамку вокруг вашего контента. Ставьте его в тон шапке приложения: несовпадение на один-два тона выглядит как ошибка вёрстки.
Оба цвета задаются в шестнадцатеричном формате. Дополнительно theme_color дублируют мета-тегом <meta name="theme-color" content="..."> — часть браузеров читает его раньше, чем манифест, и так панель не мигает при загрузке.
icons
icons — массив объектов, где у каждой иконки указаны src (путь), sizes (размеры через пробел), type (MIME-тип) и необязательный purpose. Порядок перечисления роли не играет: браузер сам выбирает подходящий размер под контекст — маленькую для списка, большую для заставки. Но перечислять нужно все размеры, которые вам нужны: «браузер увеличит» не работает, растянутая иконка мыльная.
purpose принимает значения any (обычная иконка), maskable (иконка под обрезку системной маской) и monochrome (одноцветная для тематических панелей). Про maskable подробно ниже — это место, где ломается больше всего установок.
Пример manifest.json с комментариями
Строгий JSON комментариев не допускает, поэтому в реальном файле строки с // нужно удалить — иначе парсер упадёт и браузер не прочитает ничего.
{
"name": "Название продукта", // полное имя: диалог установки, заголовок окна
"short_name": "Название", // подпись под иконкой на домашнем экране
"start_url": "/?utm_source=pwa", // точка старта, статичный параметр для аналитики
"scope": "/", // границы «своего» приложения
"display": "standalone", // своё окно без адресной строки
"orientation": "portrait", // необязательно: фиксируем ориентацию
"background_color": "#ffffff", // цвет заставки при запуске
"theme_color": "#101820", // цвет системной панели
"lang": "ru", // язык интерфейса
"dir": "ltr", // направление письма
"icons": [
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" },
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" },
{ "src": "/icons/maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
]
}lang и dir влияют на то, как система отрисует название и в какую сторону разложит элементы. orientation на мобильных фиксирует поворот экрана — полезно, но осторожно: если внутри есть формы или видео, принудительный портрет раздражает. Отсутствие scope при нестандартном start_url — приглашение к той самой поломке с выпадением разделов в браузер.
Manifest PWA generator: что делают онлайн-генераторы
Генератор манифеста — это форма, где вы заполняете поля, загружаете картинку, а на выходе получаете JSON-файл и набор иконок в нужных размерах. Работает он механически: режет исходник, подставляет пути, собирает <link> для вставки в <head>. Для черновика и быстрого старта это экономит время.
Чего генератор не знает — структуру вашего сайта. Он не подскажет, что приложение живёт в подпапке, что реальный start_url должен нести параметр для аналитики, что за nginx стоит редирект, ломающий путь к иконкам. Он также не проверяет, что исходная картинка квадратная и что из неё получится нормальная maskable-иконка: алгоритм просто обрежет и отмасштабирует, а логотип у края срежется маской.
Поэтому после генерации вывод проверяют руками по короткому списку:
- пути — абсолютные (
/icons/...) или относительные, но рабочие после сборки; откройте к
Проверено: 25.10.2026. Правила сторов и возможности платформ описаны на дату проверки; точные формулировки смотрите в официальной справке Apple, Google и MDN. Нашли неточность — напишите на redakciya@pwa-arbitrazh.com.