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 компоненты
Если задача — кастомный нативный View (например, SDK карт, кастомный видеоплеер), используем ViewManager на Android / RCTViewManager на iOS. New Architecture вводит Fabric для нативных компонентов — аналог TurboModules для вью. Codegen генерирует ComponentDescriptor по TypeScript спецификации с codegenNativeComponent.
Поддержка Expo
Если приложение на 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 дней |
| Сложный (EventEmitter, View, обе архитектуры) | от 3 до 5 недель |
Стоимость рассчитывается индивидуально. Оценим ваш проект — свяжитесь с нами для консультации.
Как мы гарантируем качество
Использование codegen исключает ошибки компиляции в рантайме. Каждый модуль проходит тестирование на реальных устройствах (iOS 15+ и Android 10+). Предоставляем сертификат совместимости с последними версиями React Native. Гарантируем бесплатную поддержку в течение 30 дней после передачи.
По данным официальной документации React Native, JSI обеспечивает снижение задержки на вызов с 1-5 мс до <0.1 мс.
Закажите разработку нативного модуля — получите консультацию наших инженеров.







