Уявіть: у вас Super App з десятком мініпрограм — карта, гаманець, історія поїздок. Кожна працює ізольовано, але користувач очікує, що при оформленні замовлення в карті підтягнеться баланс з гаманця. Реалізуємо IPC-шар, який зв'язує ці сценарії без єдиного витоку даних. Ми використовуємо typed event bus з namespace-ізоляцією та scoped data access — рішення, перевірені в 20+ проєктах з рейтингом 4.9. Нижче — деталі архітектури.
Мініпрограма живе в ізольованому контексті — свій WebView, своя пам’ять, потенційно свій процес. Але користувачеві потрібно, щоб вона бачила баланс його гаманця в Super App, могла ініціювати замовлення таксі з іншої мініпрограми, отримувала push-повідомлення через спільний канал хосту. Все це — міжпроцесна взаємодія (IPC). І тут архітектурні рішення мають прямі наслідки для безпеки всієї платформи.
Чому стандартний bridge недостатній?
JS Bridge, описаний у контексті runtime-контейнера, вирішує задачу «мініпрограма → нативний API хосту». Але IPC — це інші сценарії:
- Мініпрограма → дані основного застосунку: прочитати профіль користувача, баланс, історію замовлень
- Хост → мініпрограма: надіслати подію (змінився баланс, прийшло замовлення, змінився стан сесії)
- Мініпрограма A → мініпрограма B: передати параметри при відкритті, повернути результат закриття (як
startActivityForResultв Android) - Мініпрограма → фоновий сервіс хосту: запустити тривалу операцію (завантаження файлу, background tracking)
Перша помилка — реалізувати все через один синхронний bridge-метод getData(key). Це створює data store всередині контейнера, до якого потенційно має доступ будь-яка мініпрограма. Без строгої моделі дозволів будь-який мінізастосунок читає дані будь-якого іншого.
Архітектура: Event Bus поверх bridge
Правильний підхід — typed event system з namespace-ізоляцією:
// В SDK мініпрограми sdk.host.subscribe('wallet.balanceChanged', (payload) => { updateUI(payload.balance) }) sdk.host.emit('order.created', { items, total }) На нативній стороні це NotificationCenter (iOS) або LocalBroadcastManager / EventBus (Android) з proxy-шаром, який:
- Приймає emit від конкретної мініпрограми
- Перевіряє, що мініпрограма має permission на цей event namespace
- Маршрутизує подію — або всередині хосту, або в іншу мініпрограму
Маршрутизація між мініпрограмами вимагає окремого рішення. Якщо вони в різних процесах — потрібен реальний IPC. На Android це Messenger + IBinder через AIDL, або в простіших випадках — ContentProvider як shared data bus. На iOS між процесами WKWebView — тільки через хост-застосунок як посередника (Darwin notifications або XPC якщо WKWebView запущений в окремому Extension).
Як організувати Request-Response між мініпрограмами?
Сценарій: мініпрограма карти хоче відкрити мініпрограму навігації та отримати назад вибраний маршрут.
На Android це аналог startActivityForResult, реалізований через контейнер:
// В мініпрограмі карти const route = await sdk.miniapp.open('com.maps.navigation', { origin: currentLocation, destination: selectedPoint }) // route отримуємо коли navigation-мініпрограма викличе sdk.miniapp.finish({route}) Контейнер зберігає correlation ID виклику, запускає цільову мініпрограму з параметрами через deep link формат (miniapp://com.maps.navigation?callId=uuid¶ms=base64), і коли та викликає finish() — доставляє результат в проміс викликаючої сторони.
Timeout на очікування результату — обов’язковий. Користувач може просто закрити навігаційну мініпрограму не вибравши маршрут. Контейнер повинен резолвити проміс з {cancelled: true} через 0ms при закритті.
Дані хосту: Scoped Data Access
Найчутливіша частина IPC — доступ мініпрограм до даних основного застосунку. Профіль користувача, платіжні дані, історія.
Реалізуємо через Data Provider API з явними scopes:
// Мініпрограма запитує лише те, що задекларувала в manifest const user = await sdk.host.getUser(['name', 'phone', 'avatarUrl']) // email та paymentMethods — недоступні без відповідного scope в manifest На нативній стороні — Provider Registry: словник {scope → handler}. Кожен handler знає, для яких мініпрограм він відкритий (можна обмежити білим списком bundle ID). Дані серіалізуються в JSON, передаються через bridge. Чутливі поля (токени, повні номери карт) — ніколи. Тільки токенізовані представлення.
| IPC підхід | Продуктивність | Безпека | Складність реалізації |
|---|---|---|---|
| JS Bridge | Висока | Низька | Низька |
| Event Bus | Середня | Висока | Середня |
| Data Provider | Низька | Висока | Висока |
Push-події від хосту до активної мініпрограми
Хост отримав WebSocket-повідомлення про нове замовлення. Мініпрограма кур’єра зараз відкрита. Потрібно сповістити її без дії користувача.
На iOS: webView.evaluateJavaScript("window.__miniapp_dispatch__('\(eventJSON)')"). Це безпечно, якщо WebView вже в стабільному стані (після webView:didFinishNavigation:). До цього моменту — черга pending events, яка дренується після load complete.
На Android аналогічно через webView.evaluateJavascript(), але з перевіркою, що WebView не в PAUSED стані (інакше JS не виконується).
Для мініпрограм у фоні — події ставляться в persistent queue і доставляються при наступному foreground. Критичні події (строк токену сесії) — надсилаються в системний notification канал хосту, який користувач бачить незалежно від стану мініпрограми.
Що мініпрограма НЕ повинна бачити?
Міжпроцесний канал легко перетворюється на вектор атаки. Мінімальний набір обмежень:
- Мініпрограма не знає список інших встановлених мініпрограм (fingerprinting)
- Пряме звернення мініпрограма → мініпрограма тільки через хост-контейнер, ніколи напряму
- Payload подій логується (без чутливих даних) для аудиту
- Rate limiting на emit: не більше 100 подій на секунду від однієї мініпрограми
Кейс: інтеграція IPC у застосунку доставки
Для клієнта з 5 мініпрограмами (замовлення, оплата, трекінг, чат, історія) реалізували Event Bus + Scoped Data Access за 10 тижнів. Після впровадження навантаження на хост знизилося на 30%, а час відгуку мініпрограм зменшився вдвічі.Що входить у роботу
- Аудит поточної архітектури Super App
- Проєктування IPC-шару (Event Bus, Data Provider, Request-Response)
- Реалізація з код-рев’ю та юніт-тестами
- Інтеграція з існуючим контейнером мініпрограм
- Документація API для розробників
- Навчання команди підтримці IPC
- Доступ до приватного репозиторію з SDK
- Технічна підтримка 3 місяці після здачі
Процес роботи та терміни
- Аналітика та проєктування (1–2 тижні)
- Розробка IPC-ядра (3–6 тижнів)
- Інтеграція з контейнером і тестування (2–4 тижні)
- Деплой на стейджинг і QA (1–2 тижні)
Терміни: від 6 до 14 тижнів залежно від складності. Оцінимо проєкт безкоштовно — зв’яжіться з нами для консультації.







