React Native Library з нативним модулем: New Architecture, JSI, TurboModules
Розробка мобільного додатку часто впирається у пропрієтарні SDK вендора — інтеграція з біометрією, камерами, MDM-системами. Готові бібліотеки з React Native Community рідко покривають такі кейси, і доводиться писати нативний модуль з нуля. Ми займаємося цим більше 5 років, реалізували понад 10 проєктів з нативними модулями під iOS та Android. Наш досвід показує: правильний вибір архітектури скорочує час розробки в 2–3 рази.
Old Architecture vs New Architecture: принципова різниця
| Параметр | Old Architecture (Bridge) | New Architecture (TurboModules + JSI) |
|---|---|---|
| Механізм виклику | Асинхронний, через JSON-серіалізацію | Синхронний, прямий C++ binding |
| Затримка | 1–5 мс на виклик | < 0.1 мс |
| Робота з потоками | JS thread блокується при синхронних викликах | JS thread не блокується (модель відмінна) |
| Підтримка React Native версій | 0.68 і нижче | 0.73+ (включена за замовчуванням) |
New Architecture використовує JSI (JavaScript Interface) — прямий C++ binding між JS двигуном (Hermes) і нативним кодом. TurboModules завантажуються ліниво і викликаються синхронно. Для високочастотних операцій (кожен кадр анімації, real-time audio processing) це критично: різниця в продуктивності досягає 5–10 разів. Бібліотека повинна підтримувати обидва варіанти через codegen специфікацію.
Чому New Architecture швидше?
Стара архітектура (Bridge) працює асинхронно через серіалізацію JSON. Виклик нативного методу: JavaScript → JSON serialization → Bridge queue → deserialization → Java/ObjC. Це додає ~1-5 мс на кожен виклик і робить неможливим синхронний доступ до нативного коду. New Architecture використовує JSI (JavaScript Interface) — прямий C++ binding між JS двигуном (Hermes) і нативним кодом. TurboModules завантажуються ліниво і викликаються синхронно. Для високочастотних операцій (кожен кадр анімації, real-time audio processing) це критично.
React Native 0.73+ включає New Architecture за замовчуванням. Бібліотека повинна підтримувати обидва варіанти через codegen специфікацію.
Як створити бібліотеку через create-react-native-library
npx create-react-native-library@latest my-module — стандартний scaffold. Генерує структуру:
my-module/ android/src/main/java/…/MyModule.kt ios/MyModule.mm (Objective-C++ для JSI bridge) src/index.tsx — TypeScript API src/NativeMyModule.ts — codegen spec Codegen специфікація
TypeScript-файл описує контракт, за яким codegen генерує C++ glue code:
// NativeMyModule.ts import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { multiply(a: number, b: number): Promise<number>; getDeviceId(): string; // синхронний метод — тільки в New Architecture } export default TurboModuleRegistry.getEnforcing<Spec>('MyModule'); getEnforcing кидає помилку при старті, якщо нативний модуль не зареєстровано — краще, ніж мовчазний undefined.
Реалізація на Android: Kotlin + ReactPackage
class MyModule(reactContext: ReactApplicationContext) : NativeMyModuleSpec(reactContext) { override fun getName() = NAME override fun multiply(a: Double, b: Double): Promise<Double> { return Promise.resolve(a * b) } override fun getDeviceId(): String { return Settings.Secure.getString( reactApplicationContext.contentResolver, Settings.Secure.ANDROID_ID ) } companion object { const val NAME = "MyModule" } } NativeMyModuleSpec — абстрактний клас, згенерований codegen з TypeScript специфікації. Якщо метод не реалізовано — помилка компіляції, а не рантайм-краш. Це ключова перевага New Architecture.
ReactPackage реєструє модуль:
class MyPackage : ReactPackage { override fun createNativeModules(context: ReactApplicationContext) = listOf(MyModule(context)) override fun createViewManagers(context: ReactApplicationContext) = emptyList<ViewManager<*, *>>() } Реалізація на iOS: Objective-C++ bridge
Для New Architecture iOS-реалізація пишеться на Objective-C++ (.mm) або Swift з ObjC-обгорткою. Swift нативно не підтримує JSI без bridge, тому .mm файл з #import <React/RCTUtils.h> залишається обов'язковим.
// MyModule.mm #import "MyModule.h" #import <React/RCTUtils.h> @implementation MyModule RCT_EXPORT_MODULE() - (NSString *)getDeviceId { return [[[UIDevice currentDevice] identifierForVendor] UUIDString]; } @end Для синхронних методів в Old Architecture: RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD — працює, але блокує JS thread. В New Architecture синхронність через JSI не блокує JS thread — кардинально інша модель.
Нативні View компоненти та підтримка Expo
Якщо задача — кастомний нативний View (наприклад, SDK карт, кастомний відеоплеєр), використовуємо ViewManager на Android / RCTViewManager на iOS. New Architecture вводить Fabric для нативних компонентів — аналог TurboModules для в'ю. Codegen генерує ComponentDescriptor по TypeScript специфікації з codegenNativeComponent.
Для додатків на Expo managed workflow нативний модуль вимагає Expo Modules API замість голого React Native. npx create-expo-module генерує правильний scaffold. ExpoModule реєструється автоматично без ReactPackage — Expo Autolinking знаходить модуль по package.json.
Які типові помилки виникають?
Module not found в рантаймі
Забули запустити `pod install` на iOS після додавання модуля.Mismatched types
TypeScript spec каже `number`, Kotlin приймає `Double` (ok), Swift приймає `Int` (краш). Всі числа в JS — `Double` на нативній стороні.Main thread violation
Виклик UI-коду з нативного методу без dispatch на main thread: `DispatchQueue.main.async` / `UiThreadUtil.runOnUiThread`.Що входить у розробку нативного модуля під ключ
Наші інженери (більше 5 років досвіду в React Native) виконують:
- Аналіз вимог і проєктування API модуля
- Реалізацію нативного коду на Kotlin та Objective-C++/Swift
- Кодогенерацію TypeScript-специфікацій та інтеграцію з New Architecture
- Написання тестів (unit + integration) для обох платформ
- Збірку та публікацію в npm/Expo registry
- Документацію модуля та приклади використання
- Підтримку після релізу (виправлення багів, оновлення під нові версії RN)
Терміни та гарантії
| Тип модуля | Термін | Орієнтовна вартість |
|---|---|---|
| Простий (1-3 методи) | від 3 до 5 днів | від $500 |
| Складний (EventEmitter, View, обидві архітектури) | від 3 до 5 тижнів | від $3000 |
Вартість розраховується індивідуально. Оцінимо ваш проєкт — зв'яжіться з нами для консультації.
Використання codegen виключає помилки компіляції в рантаймі. Кожен модуль проходить тестування на реальних пристроях (iOS 15+ та Android 10+). Надаємо сертифікат сумісності з останніми версіями React Native. Гарантуємо безкоштовну підтримку протягом 30 днів після передачі.
За даними офіційної документації React Native, JSI забезпечує зниження затримки на виклик з 1-5 мс до <0.1 мс.
Замовте розробку нативного модуля — отримайте консультацію наших інженерів.







