Пользователь закрыл приложение — и связь с ним оборвалась. Push-уведомления решают эту задачу: позволяют отправить сообщение на устройство, даже когда приложение не открыто. Но в мобильном вебе существует два совершенно разных пути доставки push, и они работают по-разному на разных платформах.
Два пути: web push и нативный push
Раньше уведомления были доступны только нативным приложениям — нужно было публиковать приложение в магазине и использовать системные API. Браузеры этого не умели.
Со временем появился Web Push — стандартный браузерный механизм. Он строится на трёх составляющих:
- Push API — браузер подписывается на уведомления и получает уникальный endpoint.
- Notification API — показывает уведомление на экране.
- Service worker — принимает входящее сообщение и показывает уведомление, даже когда вкладка закрыта.
Схема работает так: бэкенд отправляет зашифрованное сообщение на endpoint пользователя, push-сервис браузера (у Google — FCM, у Apple — APNs) доставляет его, service worker просыпается и показывает уведомление.
Нативный push работает иначе: приложение в нативной обёртке регистрируется напрямую в платформенной службе доставки, получает device token и отдаёт его бэкенду. Дальше сервер отправляет сообщение через платформенный шлюз — минуя браузер.
Главное отличие:
| Web Push | Нативный push | |
|---|---|---|
| Нужна обёртка? | Нет | Да (Capacitor / магазин) |
| Работает на Android | Да | Да |
| Работает на iOS | Только установленное PWA (16.4+) | Да, надёжно |
| Настройка | Только бэкенд | Платформенная (FCM, APNs, сертификаты) |
FCM и APNs — что это такое
Нативную доставку обеспечивают две разные службы.
FCM (Firebase Cloud Messaging) — сервис Google. Бэкенд отправляет сообщение в FCM, тот доставляет его на Android-устройство.
APNs (Apple Push Notification service) — сервис Apple. Без него push на iPhone не придёт — никаким другим способом уведомление на iOS не доставить.
На практике используют такую схему: FCM выступает единым шлюзом и для iOS тоже. APNs-ключ загружается в Firebase, бэкенд работает только с FCM, а FCM сам ретранслирует сообщения в APNs. Это убирает из бэкенда вторую интеграцию.
Что потребуется настроить:
- Android — файл
google-services.jsonв проекте. - iOS — платный аккаунт Apple Developer, APNs-ключ (
.p8), включённая capability «Push Notifications» в Xcode.
Подключение через Capacitor
В приложении на Capacitor нативный push подключается плагином @capacitor/push-notifications. Он даёт единый API поверх FCM и APNs: запрос разрешения, регистрация, получение токена и обработка событий.
npm install @capacitor/push-notifications
npx cap sync
import { PushNotifications } from "@capacitor/push-notifications";
export async function registerPush(onToken: (token: string) => void) {
let status = await PushNotifications.checkPermissions();
if (status.receive === "prompt") {
status = await PushNotifications.requestPermissions();
}
if (status.receive !== "granted") {
throw new Error("push permission denied");
}
await PushNotifications.addListener("registration", (token) => {
onToken(token.value); // отправить токен на бэкенд
});
await PushNotifications.addListener("registrationError", (err) => {
console.error("push registration failed", err.error);
});
await PushNotifications.register();
}
Несколько важных моментов:
register()не показывает диалог — он только запускает регистрацию в FCM или APNs. Диалог разрешения вызывается отдельно черезrequestPermissions().- Токен приходит асинхронно в слушателе события
registration, а не как возвращаемое значение. - Возможные значения
status.receive:prompt,prompt-with-rationale(Android),granted,denied.
Разрешения и токены
Разрешение и токен — два отдельных шага, и порядок важен.
Сначала проверяют текущий статус через checkPermissions(). Если разрешение не дано, запрашивают его через requestPermissions() — это показывает системный диалог. Только при granted имеет смысл вызывать register().
Когда регистрация прошла успешно, device token нужно сохранить на бэкенде, привязав к пользователю. Именно по нему сервер потом адресует push конкретному устройству.
Токен не вечен — платформа может его сменить при переустановке, восстановлении из резервной копии или ротации ключей. Поэтому событие registration обрабатывают при каждом запуске приложения и обновляют токен на сервере.
// Push пришёл, пока приложение открыто
await PushNotifications.addListener("pushNotificationReceived", (notification) => {
console.log("received", notification.title, notification.body);
});
// Пользователь тапнул по уведомлению
await PushNotifications.addListener("pushNotificationActionPerformed", (action) => {
navigateTo(action.notification.data?.route);
});
Через поле data удобно передавать маршрут, чтобы открыть нужный экран при тапе.
Ограничения iOS
iOS — главная причина, по которой выбор пути не очевиден.
Web Push на iOS появился в версии 16.4, но с серьёзным условием: сайт должен быть установлен как PWA через «Поделиться → На экран Домой». Только тогда Push API и service worker становятся доступны. В обычной вкладке Safari web push на iPhone не работает вовсе. Плюс системный диалог разрешения можно показать только в ответ на явный жест пользователя — нельзя вызвать его автоматически при загрузке страницы.
Это и есть ключевая развилка. Если охват iOS критичен и нельзя рассчитывать, что пользователь установит PWA, надёжный путь один — нативный push через APNs в Capacitor-обёртке.
Web push на iOS остаётся хорошим вариантом для установленного PWA, но как единственный канал для iPhone он ненадёжен. На Android и компьютерах таких ограничений нет — там web push работает в полную силу.
Коротко
- Push-уведомления доставляются двумя путями: web push (браузерный стандарт) и нативный push (через FCM и APNs в Capacitor-обёртке).
- Web push работает в PWA и браузере на Android и компьютерах без какой-либо нативной упаковки.
- На iOS web push доступен только в установленном PWA (версия 16.4+) — в обычной вкладке Safari он не работает.
- FCM (Google) и APNs (Apple) — платформенные службы доставки; FCM можно использовать как единый шлюз и для Android, и для iOS.
- Плагин
@capacitor/push-notificationsдаёт единый API поверх FCM и APNs. - Device token нужно обновлять на сервере при каждом запуске — он может измениться.
- Для надёжного охвата iOS нужна Capacitor-обёртка и нативный push через APNs.
Что почитать дальше
- Capacitor — нативная обёртка для веб-приложения — как устроена обёртка, в которой работает нативный push.
- PWA — Progressive Web App — установка на домашний экран, service worker и web push без магазинов.
- Нативные API в мобильном вебе — другие возможности платформы, доступные через Capacitor.
- Когда нужно нативное приложение — где заканчиваются возможности веба.