Если вы открыли эту статью, значит, ваш менеджер или заказчик снова пришли с «гениальной» идеей: «А давайте не будем тратить бюджет на нативную iOS-разработку, а сделаем PWA? Это же кроссплатформенно, модно и дешево!». И теперь вам нужно аргументированно объяснить (или понять самому), почему в 2026 году, несмотря на все обещания открытого веба и давление регуляторов, PWA на iPhone всё ещё ощущается как гражданин второго сорта.
В этом тексте не будет маркетинговой шелухи про «единый код для всех». Мы разберем суровую техническую реальность Safari 19, ограничения WebKit, о которых Apple предпочитает молчать, и те немногие лазейки, которые позволяют сделать опыт использования веб-приложений хотя бы терпимым. Вы узнаете, почему localStorage умирает при установке, как заставить работать Deep Links (и почему они все равно ломаются), и в каких редких случаях PWA действительно может заменить App Store. Это гайд по выживанию в экосистеме, которая активно сопротивляется вашему присутствию.
PWA на iOS в начале 2026: реальность против ожиданий
Давайте сразу снимем розовые очки. На дворе январь 2026 года. iOS 19 уже на миллионах устройств. Евросоюз со своим DMA (Digital Markets Act) вроде бы заставил Apple приоткрыть калитку для сторонних браузерных движков, но для 90% пользователей (за пределами ЕС) ситуация глобально не изменилась. Safari остается бутылочным горлышком.
Главная проблема PWA на iOS - это не отсутствие API (их завезли достаточно), а намеренное ухудшение UX. Apple делает всё, чтобы пользователь чувствовал разницу между «настоящим» приложением и «ярлыком сайта».
Safari 19: шаг вперед, два назад
Мы получили Web Push (наконец-то стабильный), мы получили частичную поддержку Web Bluetooth, но мы до сих пор упираемся в базовые вещи:
Установка приложения - это квест. В отличие от Android, где браузер сам кричит пользователю: «Установи меня!» через
beforeinstallprompt, на iOS вы не можете программно вызвать нативное окно установки. Всё, что у вас есть - это ваш собственный HTML-баннер со стрелочкой, указывающей на кнопку «Поделиться», и инструкция: «Нажмите "На экран Домой"». Это ломает конверсию в установку катастрофически.Синхронизация в фоне - мертва. Background Sync API вроде бы есть в спецификациях, но на практике iOS убивает процесс PWA почти мгновенно после сворачивания. Если пользователь нажал «Отправить отчет» и свернул приложение при плохом интернете - отчет не уйдет.
Изоляция хранилища. Если пользователь не добавил ваше PWA на домашний экран, Safari удалит все данные (LocalStorage, IndexedDB, Service Worker Cache) через 7 дней отсутствия активности (ITP). Это часть Intelligent Tracking Prevention (ITP). Вы строите офлайн-приложение, а через неделю пользователь возвращается к чистому листу.
Чего всё ещё нет: iOS vs Android (Chrome)
Я часто слышу аргумент: «Но ведь PWA теперь поддерживают пуши!». Да, поддерживают. Но дьявол в деталях. Вот таблица боли, которую я составляю для каждого нового проекта.
Фича | Android (Chrome) | iOS (Safari / WebKit) | Комментарий разработчика |
|---|---|---|---|
Install Prompt | Нативный, программный вызов | Отсутствует. Только ручной выбор в Share | Главный убийца конверсии. |
Push Notifications | Работают "из коробки" | Только если добавлено на Home Screen | Без иконки на экране пушей не будет. |
Service Workers | Живут долго, будят приложение | Убиваются агрессивно | Apple экономит батарею (и нервы нативной команды). |
Deep Linking | Intent Filters (стабильно) | Universal Links (нестабильно) | Работает, но зависит от "настроения" iOS. |
Bluetooth / NFC | Полная поддержка | Нет или крайне ограничено | Забудьте про работу с оборудованием. |
App Store | Можно запаковать (TWA) | Запрещено | PWA как таковое в App Store не пустят. |
Deep Linking: ад перфекциониста
Вы сделали PWA. Вы хотите, чтобы ссылка из email или SMS открывала именно PWA, если оно установлено, а не Safari. Работает ли это в 2026 году?
Да, работает. Но с оговорками.
Если PWA уже установлено на iPhone, то переход по ссылке (например, из Заметок, iMessage или Почты) может открыть PWA. Но для этого нужно выполнить строгие условия, и даже тогда успех не гарантирован.
Что нужно для настройки:
Associated Domains (AASA):
Раньше это было только для нативных приложений, но теперь PWA тоже поддерживают файл
apple-app-site-association. Ваш сервер должен отдавать этот файл в корне (/.well-known/apple-app-site-association), подтверждая, что этот домен принадлежит этому приложению. Реализация черезmanifest.jsonчасто глючит, поэтому надежнее делать серверную верификацию.Scope в манифесте:
Ссылка, по ��оторой переходит пользователь, должна лежать строго внутри
scope, указанного в вашемmanifest.json. Еслиscopeэто/app/, а ссылка ведет на/promo/, откроется Safari.«Настроение» iOS:
Это главная проблема. Даже при идеальной настройке iOS часто все равно открывает ссылку в Safari, показывая сверху маленькую, едва заметную плашку «Открыть в [Название PWA]». Это не тот бесшовный опыт (Intent Filters), который есть на Android, где система сразу перебрасывает в приложение. Apple как бы говорит: «Мы знаем, что у тебя есть приложение, но мы откроем браузер, потому что мы так решили».
Deferred Deep Linking: как не потерять пользователя при установке
Теперь перейдем к более сложной задаче. Сценарий:
Пользователь кликает на реф-ссылку
myapp.com/invite/friend123в Safari.Приложения у него нет.
Он устанавливает его («На экран Домой»).
Открывает установленное PWA.
Приложение должно знать, что это был
friend123, и показать нужный экран.
И вот тут многие разработчики (и я в прошлом) совершают фатальную ошибку, полагаясь на localStorage.
Миф о Shared Storage (общем хранилище)
Вам может показаться логичным сохранить токен в localStorage в Safari, а потом прочитать его в PWA. Это не сработает.
Начиная с iOS 14.5+ и окончательно закрепив в последних версиях, Apple ввела жесткую изоляцию - State Partitioning.
Safari - это один изолированный контейнер.
Установленное PWA - это совершенно другой, герметичный контейнер.
Они не делят общее ��ранилище в реальном времени. Если вы залогинитесь на сайте в Safari, а потом добавите его на экран - в PWA вы откроетесь «голым» и разлогиненным. localStorage будет пустым.
Трюк «Copy-on-install»: почему Cookies - ваше спасение
Так как же передать данные? Единственный рабочий механизм - это использование Cookies и знание того, как именно iOS создает PWA.
Когда пользователь нажимает кнопку «Add to Home Screen», iOS делает моментальный снимок (snapshot) текущего состояния Cookies из Safari и копирует их в новый создаваемый контейнер PWA.
Это разовая акция. Синхронизации в будущем не будет, но в момент рождения PWA наследует куки родителя-Safari.
Почему именно Cookies, а не LocalStorage?
По моим наблюдениям и тестам на iOS 17–19, при создании этого снапшота:
Cookies: Копируются почти всегда (если они не
HttpOnlyи имеют правильные флаги безопасности, напримерSameSite=Lax).localStorage / sessionStorage: Часто НЕ копируются. PWA открывается с девственно чистым стораджем.
Правильный алгоритм реализации (Deferred Deep Linking)
Вот как это нужно делать в коде, чтобы реферальная система работала:
User Land: Пользователь заходит на
myapp.com/?ref=friend123в Safari.Server/JS: Вы парсите URL и записываете
friend123в Cookie.document.cookie = "ref_context=friend123; path=/; max-age=3600; SameSite=Lax";Важно:
path=/обязателен, иначе кука может потеряться при смене пути.Install: Пользователь добавляет PWA на экран. В этот момент iOS копирует куку
ref_contextв пакет приложения.Launch: PWA запускается. Даже если
start_urlв манифесте стоит просто/, приложение открывается в своем контейнере, где уже лежит скопированная кука.Init Code: При старте JS проверяет наличие куки:
const getCookie = (name) => { /* ... */ }; const ref = getCookie('ref_context'); if (ref) { // Активируем логику для friend123 // И сразу перекладываем в надежное место, если нужно }
Рабочие обходные пути (без нарушения правил App Store)
Раз уж мы разобрались с хранилищем, давайте посмотрим, как еще можно улучшить жизнь пользователя.
1. Smart App Banners для PWA
Apple не дает нативного баннера для PWA, но мы можем сделать свой. Главное - не показывать его тем, кто уже установил приложение.
CSS media query, который спасает жизни:
/* Показываем кнопку установки только в браузере */
.install-banner { display: block; }
/* Скрываем, если запущено как PWA (standalone) */
@media all and (display-mode: standalone) {
.install-banner {
display: none;
}
}В JavaScript это проверяется так:
const isStandalone = window.navigator.standalone || matchMedia('(display-mode: standalone)').matches;2. Сохранение состояния форм (Persistence)
Поскольку iOS любит убивать PWA в фоне при малейшей нехватке памяти, пользователь, переключившийся на Telegram ответить на сообщение, может вернуться к перезагруженной странице и пустой форме.
Совет: Никогда не надейтесь на память состояния React/Vue. Пишите черновики в localStorage (внутри уже запущенного PWA он работает нормально) на событие onInput. При загрузке страницы проверяйте сторадж и восстанавливайте данные. Это создаст иллюзию «нативной» многозадачности.
Когда PWA на iOS - это разумный выбор
Я не хочу что бы вы подумали, будто PWA - это абсолютное зло. Есть ниши, где это идеальное решение, даже с учетом ограничений Apple.
Внутренние корпоративные инструменты (Intranet). Сканеры штрих-кодов на складе, дэшборды. Вам не нужно проходить ревью App Store, которое может занять дни. Вы обновили код - у всех сотрудников новая версия.
B2B сервисы с редким использованием. Если вашим сервисом пользуются раз в месяц для оплаты счета, никто не будет качать приложение на 200 МБ. PWA здесь выигрывает.
Ивент-приложения. Конференции, фестивали. Быстрый доступ к расписанию в офлайне без необходимости идти в магазин приложений.
Когда вам НУЖЕН натив (или React Native / Flutter - хотя там свои тараканы)
PWA на iOS станет вашей могилой, если ваш проект требует следующего:
Надежная геолокация в фоне: Трекеры бега, логистика. PWA теряет доступ к GPS, как только гаснет экран.
Сложная работа с камерой: AR-маски, кастомная обработка видеопотока. WebRTC в Safari работает, но превращает ваш телефон в раскаленный кирпич и часто вылетает.
Биометрия: Да, WebAuthn есть, но он выглядит как вход на сайт, а не как нативная проверка FaceID. Это снижает доверие в финтехе.
Большие объемы данных: Если нужно хранить гигабайты видео офлайн. Риск, что Safari молча почистит кэш, слишком велик.
Итог
В 2026 году PWA на iOS - это всё ещё история про компромиссы и знание скрытых механизмов, вроде копирования кук при установке. Apple построила систему так, что PWA может работать, но никогда не будет работать слишком хорошо, чтобы не угрожать доходам App Store.
Если вы выбираете этот путь, ваша главная задача - управление ожиданиями. Вы должны четко понимать разницу между «Работает в Chrome» и «Работает в Safari». И, к сожалению, для iOS вам придется писать отдельный слой кода, который будет обслуживать капризы этой платформы.
