Day 33: Fabric Renderer & TurboModules Mechanics
Understand Fabric as React Native's Fiber-aware, JSI-backed renderer, and TurboModules as lazily-loaded, synchronously-callable native modules.
Study
Concepts
Fabric: the New Architecture's UI renderer
Fabric replaces the old Shadow Thread / UIManager pipeline with a renderer built on JSI and a shared C++ core: React's Fiber tree (Day 21) can now hold direct references to C++ "Shadow Nodes" instead of communicating layout changes through serialized Bridge messages. Layout (via Yoga) and committing to the actual native view tree happen through this shared C++ layer, allowing high-priority updates (like a user's active gesture) to be processed with less overhead and, critically, synchronously when needed instead of always waiting for the next Bridge batch.
A practical consequence: Fabric enables features like synchronous layout effects that actually reflect real native measurements immediately, and better interoperability for gesture-driven, native-thread-bound libraries (Reanimated 2/3, Gesture Handler) that want to skip the JS thread entirely for certain updates.
TurboModules: lazy-loaded, JSI-backed native modules
In the old architecture, ALL native modules were eagerly initialized at app startup, whether or not they were ever used — a real cost on cold start for large apps with many linked libraries. TurboModules are loaded LAZILY, on first use, and are backed by JSI Host Objects, so calling one can be synchronous and does not require the JSON-serialize-and-queue dance. Codegen (Day 34) generates the C++/type-safe glue between your JS-declared spec and the native implementation, which is also what makes TurboModules strongly typed end-to-end.
The net effect of Fabric + TurboModules together: faster app startup (lazy loading), lower memory usage (unused modules never initialize), and lower latency for native interactions (no serialization, synchronous when needed) — this is the concrete payoff of the JSI investment from Day 32.
See It
Visualizations
Visualization
Fabric + TurboModules on top of JSI
Build It
Code Examples
A TurboModule spec (TypeScript) — the source of truth for Codegen
// NativeDeviceInfo.ts
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
getBatteryLevelSync(): number; // now CAN be truly synchronous
getDeviceModel(): Promise<string>; // async is still supported when appropriate
}
export default TurboModuleRegistry.getEnforcing<Spec>('DeviceInfo');Consuming it — lazy-loaded on first access
import DeviceInfo from './NativeDeviceInfo';
// Native module is NOT initialized at app startup — only the first
// time something actually imports/calls it, unlike the old architecture.
const level = DeviceInfo.getBatteryLevelSync(); // synchronous, JSI-backed
const model = await DeviceInfo.getDeviceModel(); // still fine to keep async where it makes senseRemember
Key Takeaways
- Fabric moves layout/commit onto a shared JSI-backed C++ core, enabling synchronous, priority-aware UI updates.
- TurboModules load lazily on first use instead of all-at-once at startup — a direct win for cold-start time and memory.
- TurboModules are backed by JSI Host Objects, so calls can be synchronous and skip JSON serialization entirely.
- Codegen (Day 34) generates the typed glue between a JS module spec and its native implementation for both Fabric components and TurboModules.
- Together, Fabric + TurboModules are the concrete performance payoff that JSI (Day 32) made structurally possible.
Do It
Practice
- 1Create a minimal TurboModule spec file for a hypothetical "Clipboard" module with one sync and one async method.
- 2Read the React Native New Architecture working group docs and list 3 libraries that ship New Architecture support today.
- 3Compare app cold-start time (conceptually) between an app with 30 eagerly-initialized old-architecture native modules vs the same app on TurboModules.