Web-first приложение на iOS — это веб-код, исполняемый внутри нативной обёртки, и эта обёртка на iOS ровно одна: WKWebView. Понять её движок, лимиты и правила App Store важно потому, что именно здесь web-first-подход упирается в самые жёсткие ограничения платформы — и где чаще всего ломается выход в магазин. Продукт-инженеру это нужно, чтобы оценить, влезает ли продукт в мобильную стратегию на iOS, до того как написана первая строка нативного кода.

WKWebView как движок

WKWebView — современный движок веб-контента на iOS, пришедший на смену устаревшему UIWebView: отдельный процесс рендеринга, аппаратное ускорение, актуальный JavaScript-движок. Ключевой факт платформы: все браузеры на iOS обязаны использовать WebKit — и Safari, и сторонние браузеры рендерят страницы одним и тем же движком (исключение — альтернативные движки в EU с iOS 17.4, но в обёртках это не задействуется). Для web-first это значит: поведение веба внутри приложения предсказуемо, оно совпадает с Safari той же версии iOS.

Capacitor на iOS работает именно поверх WKWebView — не поверх UIWebView и не поверх своего движка. Веб-сборка кладётся в нативный проект и грузится в WKWebView с локального origin, а мост даёт доступ к нативным API через плагины.

Что iOS ограничивает для веба

Чистый веб на iOS (PWA, добавленная на домашний экран) живёт по урезанным правилам, и это главный аргумент против отказа от обёртки. Меньше доступа к нативным API: значительная часть push-уведомлений, фоновых задач и интеграций недоступна вебу напрямую. Лимиты хранилища: Web Storage (localStorage и sessionStorage) ограничен примерно 5 МБ на origin, а общая квота на origin для встраиваемого контента — порядка 15% дискового пространства, с риском вытеснения данных WebKit при нехватке места. Нет полноценного фона: service worker и фоновое выполнение в standalone-режиме работают ограниченно, а медиа и геолокация обычно встают на паузу при уходе приложения в фон.

Обёртка через WKWebView эти ограничения не снимает целиком — лимиты движка те же, — но даёт нативный слой поверх веба, через который недостающие возможности добираются плагинами.

Сборка под iOS

Сборка под iOS идёт через Xcode и требует аккаунта Apple Developer: подпись (signing) и provisioning profile обязательны даже для запуска на устройстве. С Capacitor поток такой:

npm run build
npm install @capacitor/ios
npx cap add ios
npx cap sync
npx cap open ios

npx cap sync копирует собранную веб-сборку (webDir из конфига) в нативный проект и обновляет нативные зависимости; npx cap open ios открывает .xcworkspace в Xcode, где задаются bundle identifier, команда подписи и target. iOS 15+ и актуальный Xcode — базовое требование Capacitor.

Для отладки веба внутри обёртки в релизных сборках есть отдельный флаг — иначе Safari Web Inspector к релизной сборке не подключится:

import type { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'ru.example.app',
  appName: 'Example',
  webDir: 'dist',
  ios: {
    webContentsDebuggingEnabled: true,
  },
};

export default config;

В отладочных сборках инспекция включена по умолчанию; для релизной сборки флаг по умолчанию false — оставлять true в релизе не нужно.

Публикация в App Store и ревью

Главная засада web-first именно здесь. App Store Review Guideline 4.2 (minimum functionality) прямо требует, чтобы приложение давало нативную ценность, а не было голой обёрткой вокруг сайта. Приложение, которое целиком сводится к WebView с тем же сайтом и не делает ничего, чего не делает мобильный браузер, ревьюер отклоняет: «не отличается от веб-сёрфинга». Это не теоретический риск — это самая частая причина отказа для таких приложений.

Чтобы пройти 4.2, веб-сборку оборачивают нативной ценностью: push-уведомления, нативные интеграции (камера, биометрия, файлы, системный обмен), офлайн-режим, нативная навигация и хорошее поведение на устройстве. Сам по себе тот же контент в WKWebView ревью не проходит — отличие от браузера должно быть заметным. Если нативной ценности нет, честнее остаться PWA и не идти в магазин вовсе.

TestFlight

До публичного релиза сборка раздаётся через TestFlight — бета-раздачу Apple. Сборка загружается в App Store Connect; внутренним тестировщикам (до 100 человек из команды) она доступна почти сразу, внешним (до 10 000 человек, по e-mail-приглашению или публичной ссылке) — после прохождения beta-ревью. Первая сборка версии требует полного ревью, последующие могут его не проходить. TestFlight позволяет проверить web-first-обёртку на реальных устройствах и iOS-версиях до того, как продукт встретит ревьюера App Store.

Где это в UCP

iOS — самая ограничивающая платформа для web-first: один движок WKWebView, жёсткие лимиты веба и ревью по гайдлайну 4.2, отклоняющее голые обёртки. Продукт-инженер держит эти правила в голове на этапе решения, а не на этапе отказа в магазине: на iOS web-first проходит только с нативной ценностью поверх веба. Зеркальный расклад на другой платформе разбирается в статье про Android и TWA, а граница, за которой обёртки уже не хватает, — в когда нужен native.