Новая архитектура: JSI, Fabric, TurboModules и Hermes

Вопрос уровня middle+ и senior: что именно изменила новая архитектура и какие проблемы старой она решает.

JSI (JavaScript Interface) — тонкий слой на C++, через который JS-код может напрямую, синхронно и без сериализации обращаться к нативным объектам. Это фундамент, на котором стоят Fabric и TurboModules.

Вопрос

«Расскажите про новую архитектуру React Native: что такое JSI, Fabric, TurboModules и Codegen? Что даёт Hermes?»

Что на самом деле проверяет интервьюер

Здесь смотрят, следит ли кандидат за развитием платформы и умеет ли связать «модные слова» с конкретными проблемами. Хороший ответ строится не как список терминов, а как история: вот ограничение старой архитектуры — вот чем его закрыли.

Развёрнутый ответ

JSI — замена bridge

JSI позволяет создать JS-объект, который на самом деле является обёрткой над нативным объектом C++ (так называемый HostObject). Обращение к его методу — это прямой вызов, без очереди и без JSON. Появляются две вещи, невозможные раньше: синхронные вызовы и передача ссылок вместо копирования данных.

// Новая архитектура: значение можно прочитать синхронно
const value = global.__MMKV.getString('token');
console.log(value);

// Старая архитектура: только асинхронно, через очередь
AsyncStorage.getItem('token').then((token) => console.log(token));

Именно поэтому библиотеки нового поколения (MMKV, Reanimated, Skia, быстрые SQLite-обёртки) стали возможны: они держат нативный объект прямо в JS.

TurboModules — нативные модули по требованию

В старой архитектуре список всех нативных модулей инициализировался при старте приложения, даже если пользователь никогда не откроет камеру. TurboModules ленивы: модуль создаётся в момент первого обращения. Плюс их API описывается спецификацией, а вызовы идут через JSI.

// NativeDeviceInfo.ts — спецификация модуля, источник правды для Codegen
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';

export interface Spec extends TurboModule {
  getDeviceName(): string;          // синхронный вызов — раньше так было нельзя
  getBatteryLevel(): Promise<number>;
}

export default TurboModuleRegistry.getEnforcing<Spec>('DeviceInfo');

Codegen — типобезопасность на границе

По такой спецификации на этапе сборки генерируется нативная обвязка на C++, Java и Objective-C. Раньше несовпадение типов между JS и нативным кодом обнаруживалось в рантайме падением приложения; теперь его ловит компилятор.

Fabric — новый рендерер

Fabric переписывает слой рендеринга на C++ и даёт три важные вещи:

  • Общее дерево. Дерево view хранится в C++ и доступно обеим сторонам, без асинхронной синхронизации состояний.
  • Синхронные измерения. Layout можно посчитать и применить в том же кадре — исчезает класс багов с «прыгающим» интерфейсом.
  • Совместимость с конкурентным React. Поддержка Suspense, приоритетов обновлений и прерываемого рендера.

Hermes — движок JS для мобильных

Hermes создавался под задачу «быстро стартовать на дешёвом Android». Ключевое отличие: JS компилируется в байт-код заранее, при сборке, а не парсится при каждом запуске. Итог — заметно меньшее время холодного старта, меньший расход памяти и меньший размер приложения. Отладка идёт через Chrome DevTools по протоколу Hermes, а не через удалённый JS-отладчик.

# проверить, какой движок используется в собранном приложении
npx react-native info

# в JS можно спросить в рантайме
node -e "console.log('в приложении: global.HermesInternal !== undefined')"

Что это меняет на практике

Проблема старой архитектурыЧем закрыта
Асинхронность любого нативного вызоваJSI: синхронные вызовы
Сериализация в JSONJSI: ссылки на объекты
Все модули стартуют разомTurboModules: ленивая инициализация
Рассинхрон layout и рендераFabric: общее C++ дерево
Ошибки типов в рантаймеCodegen: проверка при сборке
Долгий холодный стартHermes: байт-код заранее

Типичные ошибки кандидатов

  • Говорят «новая архитектура — это Fabric», забывая, что Fabric и TurboModules стоят на JSI, а JSI — главное изменение.
  • Называют Hermes частью новой архитектуры. Hermes — независимый движок JS, он работал и со старой.
  • Обещают, что новая архитектура «делает приложение быстрым сама по себе». Она убирает ограничение границы, но кривой рендер списка останется кривым.
  • Не могут привести пример библиотеки, которой JSI дал новую жизнь (MMKV, Reanimated, react-native-skia).

Как ответить кратко

«Основа новой архитектуры — JSI: C++ слой, через который JS держит ссылку на нативный объект и вызывает его синхронно, без JSON. На нём стоят TurboModules — ленивые нативные модули с типизированной спецификацией, по которой Codegen генерирует обвязку при сборке, — и Fabric, новый рендерер с общим C++ деревом, синхронными измерениями и поддержкой конкурентного React. Hermes — отдельная история: движок JS, компилирующий код в байт-код заранее, что ускоряет холодный старт и экономит память.»

Проверьте себя
1. Что принципиально нового даёт JSI по сравнению с bridge?
AОн ускоряет сериализацию JSON примерно втрое
BОн позволяет JS держать ссылку на нативный объект и вызывать его методы синхронно, без сериализации
CОн переносит выполнение JS на UI-поток
DОн заменяет JavaScript на TypeScript в рантайме
2. Зачем в новой архитектуре нужен Codegen?
AОн генерирует иконки и ресурсы приложения при сборке
BОн по TypeScript- или Flow-спецификации модулей и компонентов генерирует типобезопасный C++, Java и Objective-C обвязочный код
CОн компилирует JS в машинный код
DОн автоматически пишет тесты для нативных модулей
3. Чем Hermes отличается от JavaScriptCore в контексте мобильного приложения?
AHermes выполняет JS на UI-потоке, поэтому нет задержек
BHermes компилирует JS в байт-код заранее, на этапе сборки, что сокращает время старта и потребление памяти
CHermes умеет выполнять нативный код Swift и Kotlin
DHermes не поддерживает отладку и используется только в production