Реалізація Hot-завантаження міні-програм без оновлення основної додатка
Головна перевага міні-програм над нативними додатками — можливість розгорнути нову версію користувачам миттєво, без App Store Review та без користувацької дії. Виправити JS-баг вечері, вранці всі користувачі вже на новій версії. Це працює, якщо hot-loading реалізований правильно. Якщо ні — користувачі бачать старий баг тижнями, або гірше, падаючий екран після оновлення bundle, яке прийшло з помилкою.
Як влаштована система гарячої завантаження
Hot-loading для міні-програм — це не те саме, що Hot Module Replacement у Webpack. Це CDN-based delivery system з версійним контролем та rollback-можливістю.
Базовий flow:
- Розробник публікує нову версію міні-програми (новий bundle.zip на CDN)
- Платформа оновлює manifest — JSON з метаданими та URL нового bundle
- Super App періодично (або при запуску) перевіряє manifest-сервер
- Якщо версія змінилась — завантажує новий bundle у фоні
- При наступному відкритті міні-програми — завантажується новий bundle
Чорт у деталях кроків 3-5.
Стратегії перевірки оновлень
Polling при старті хоста. Найпростіше: при кожному запуску Super App фоновий сервіс перевіряє manifest для всіх встановлених міні-програм. На 50 міні-програм — 50 HTTP-запитів або один batch-запит з bulk manifest API. Затримка оновлення: до наступного запуску додатка, в середньому кілька годин.
Long polling / Server-Sent Events. Хост тримає відкрите з'єднання з manifest-сервером. При публікації нової версії сервер push-сповіщує всіх підключених клієнтів. Миттєва доставка, але: постійне з'єднання нищить батарею та трафік, нестабільно на мобільних мережах. Підходить для enterprise-додатків, де важлива миттєва доставка оновлень.
Silent Push Notification. APNs background push (iOS) або FCM data message (Android) при публікації нової версії. Система будить додаток у фоні на 30 секунд (iOS) або без явного ліміту (Android з Doze mode обмеженнями), він завантажує bundle. Оптимальний баланс між швидкістю доставки та battery impact. Обмеження на iOS: APNs silent push може бути задроттлен системою.
На практиці комбінуємо: silent push як основний канал + polling при запуску як fallback для пристроїв, де push не дійшов.
Атомарне застосування оновлення
Критичний момент: не можна застосовувати bundle під час активного сеансу міні-програми. Якщо замінити файли поки WebView працює — краш гарантований.
Рішення — staged swap:
/miniapps/com.vendor.app/
current/ <- поточний active bundle (v2.3.1)
pending/ <- завантажений, але ще не застосований (v2.3.2)
rollback/ <- попередній bundle для відкату (v2.3.0)
pending стає current тільки при наступному холодному старті міні-програми. Переіменування директорії — атомарна операція на рівні FS. Якщо у момент swap сталася крещ хоста — pending залишиться як є, і повторна спроба при наступному запуску.
Верифікація перед застосуванням
Перед застосуванням нового bundle — верифікація:
// iOS
let expectedHash = manifest.bundleHash // "sha256:a3f8c2..."
let actualHash = SHA256.hash(data: bundleData).hexString
guard "sha256:\(actualHash)" == expectedHash else {
throw BundleError.hashMismatch
}
Додатково: перевірка цифрового підпису маніфесту (платформа підписує manifest приватним ключем, клієнт верифікує публічним). Це захищає від атак, коли CDN замінює bundle на шкідливий.
Якщо верифікація провалилась — bundle видаляється, продовжуємо використовувати поточну версію. В аналітику — подія з hash mismatch для моніторингу.
Rollback при краші
Нова версія bundle може містити JS-помилку, яка призводить до краш-петлі. Потрібен автоматичний rollback.
Механізм: контейнер рахує consecutive crashes при завантаженні міні-програми. Якщо 3 краші поспіль при старті — відкатуємось на rollback/ директорію (попередня відомо-робоча версія). Подія в аналітику, сповіщення розробнику через портал.
Що вважається кращем: WKWebView навігація завершилась з помилкою, або JS кинув uncaught exception протягом 2 секунд після завантаження, або bridge не відповів на init-handshake за 5 секунд.
На стороні платформи — можливість emergency rollback: змінити currentVersion у manifest на попередню. Всі клієнти, які перевірили manifest, завантажать «старий» bundle. Це виконується за хвилини, не години.
Диференціальні оновлення
При великих bundle (> 1 MB) — диференціальні патчі замість повної заміни. Алгоритм bsdiff: для оновлення v2.3.1 → v2.3.2 генерується патч-файл, який у 10-30 разів менший від повного bundle. Клієнт завантажує патч, застосовує до поточного bundle, отримує новий.
Вимагає зберігання бінарного bundle на клієнті (не тільки розпакованих файлів) для застосування патча. Ускладнює реалізацію, але критично важливо для користувачів з повільним інтернетом.
Терміни реалізації системи hot-loading з нуля (manifest API + CDN + client-side завантажувач з верифікацією + rollback): від 6 до 12 тижнів. З диференціальними патчами — додайте ще 3-4 тижні.







