React Native New Architecture - Fabric y TurboModules en producción
Después de años de espera, la nueva arquitectura de React Native está lista
El contexto
React Native 0.74+ trae la nueva arquitectura habilitada por defecto. Después de años de desarrollo, Fabric y TurboModules están listos para producción.
Migramos una app de 100k usuarios. Aquí está nuestra experiencia.
¿Qué es la nueva arquitectura?
Arquitectura vieja (Bridge)
JavaScript ←→ Bridge (JSON) ←→ Native
(asíncrono, serialización)
Problemas:
- Serialización JSON lenta
- Comunicación asíncrona obligatoria
- No puede compartir memoria
Arquitectura nueva
JavaScript ←→ JSI ←→ Native
(síncrono, memoria compartida)
Componentes:
- JSI (JavaScript Interface): C++ layer para comunicación directa
- Fabric: Nuevo sistema de renderizado
- TurboModules: Módulos nativos con lazy loading
- Codegen: Generación de código type-safe
Habilitando la nueva arquitectura
React Native 0.74+
// react-native.config.js
module.exports = {
project: {
ios: {},
android: {},
},
};
# ios/Podfile
ENV['RCT_NEW_ARCH_ENABLED'] = '1'
# android/gradle.properties
newArchEnabled=true
cd ios && pod install
cd android && ./gradlew clean
Migración de componentes nativos a Fabric
Componente viejo (Paper)
// Android - MyViewManager.java
public class MyViewManager extends SimpleViewManager<MyView> {
@Override
public String getName() {
return "MyView";
}
@ReactProp(name = "color")
public void setColor(MyView view, String color) {
view.setBackgroundColor(Color.parseColor(color));
}
}
Componente nuevo (Fabric)
// MyView.ts - Spec file
import type { ViewProps } from 'react-native';
import type { HostComponent } from 'react-native';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
interface NativeProps extends ViewProps {
color?: string;
}
export default codegenNativeComponent<NativeProps>('MyView') as HostComponent<NativeProps>;
// Android - MyViewManager.java (actualizado)
@ReactModule(name = MyViewManager.NAME)
public class MyViewManager extends SimpleViewManager<MyView>
implements MyViewManagerInterface<MyView> {
public static final String NAME = "MyView";
@Override
public String getName() {
return NAME;
}
@Override
@ReactProp(name = "color")
public void setColor(MyView view, @Nullable String color) {
if (color != null) {
view.setBackgroundColor(Color.parseColor(color));
}
}
}
Migración de módulos nativos a TurboModules
Módulo viejo
@ReactModule(name = "Calculator")
public class CalculatorModule extends ReactContextBaseJavaModule {
@ReactMethod
public void add(double a, double b, Promise promise) {
promise.resolve(a + b);
}
}
TurboModule
// NativeCalculator.ts - Spec
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
add(a: number, b: number): Promise<number>;
// Métodos síncronos ahora posibles!
multiply(a: number, b: number): number;
}
export default TurboModuleRegistry.getEnforcing<Spec>('Calculator');
// CalculatorModule.java
public class CalculatorModule extends NativeCalculatorSpec {
@Override
public void add(double a, double b, Promise promise) {
promise.resolve(a + b);
}
// ¡Método síncrono! Imposible con bridge viejo
@Override
public double multiply(double a, double b) {
return a * b;
}
}
Codegen
Genera código C++ automáticamente desde specs TypeScript:
# Generar código
cd android && ./gradlew generateCodegenArtifactsFromSchema
# Archivos generados en:
# android/app/build/generated/source/codegen/
Performance: Antes vs Después
Benchmarks en nuestra app:
Startup time
Vieja arquitectura: 2.8s
Nueva arquitectura: 1.9s (-32%)
Lista con 1000 items (scroll FPS)
Vieja arquitectura: 45 FPS (drops a 20)
Nueva arquitectura: 58 FPS (estable)
Llamadas nativas
Vieja (Bridge): 0.5ms por llamada
Nueva (JSI): 0.02ms por llamada (-96%)
Memory
Vieja arquitectura: 180MB
Nueva arquitectura: 145MB (-19%)
Problemas encontrados
1. Librerías no compatibles
Error: TurboModuleRegistry.getEnforcing(...): 'OldLibrary' could not be found
Solución: Actualizar librería o usar interop layer:
// Para librerías viejas que no soportan TurboModules
// React Native incluye interop automático
2. Crashes en shadow nodes
Fatal: Attempt to access ShadowNode that no longer exists
Causa: Componente custom mal migrado a Fabric.
Solución: Revisar lifecycle del componente nativo.
3. Reanimated issues
# Versión compatible
npm install react-native-reanimated@3.6.0
Reanimated 3.x es compatible con nueva arquitectura.
4. Hermes obligatorio
Nueva arquitectura requiere Hermes:
# ios/Podfile
:hermes_enabled => true
Librerías compatibles
✅ Compatibles:
- react-native-reanimated 3.x
- react-native-gesture-handler 2.x
- react-native-screens 3.x
- react-native-svg 14.x
- @react-navigation/* 6.x
⚠️ Parcialmente compatibles:
- Algunas librerías con interop layer
❌ No compatibles:
- Librerías sin mantenimiento activo
- Librerías con bridge muy custom
Estrategia de migración
Fase 1: Preparación (2 semanas)
# Actualizar React Native
npx react-native upgrade 0.74.0
# Actualizar dependencias
npm update
# Verificar compatibilidad
npx react-native-new-arch-helper
Fase 2: Habilitar en desarrollo (1 semana)
# android/gradle.properties
newArchEnabled=true
Testing exhaustivo en desarrollo.
Fase 3: Migrar módulos custom (2-4 semanas)
Migrar nuestros módulos nativos a TurboModules.
Fase 4: Beta con usuarios reales (2 semanas)
Release a 10% de usuarios, monitorear crashes.
Fase 5: Rollout completo
100% de usuarios.
Monitoreo post-migración
// Crashlytics custom attributes
import crashlytics from '@react-native-firebase/crashlytics';
crashlytics().setAttribute('architecture', 'new');
// Comparar crash rates entre arquitecturas
¿Vale la pena migrar?
Sí, si:
- Tienes problemas de performance
- Mantienes módulos nativos propios
- Planeas largo plazo con React Native
Espera, si:
- App funciona bien actualmente
- Dependes de librerías no actualizadas
- No tienes tiempo para testing exhaustivo
Resultados en producción
Después de 3 meses con nueva arquitectura:
- Crash rate: 0.8% → 0.5%
- ANRs (Android): -40%
- User complaints performance: -60%
- App Store rating: 4.2 → 4.5
La migración tomó 6 semanas pero valió cada hora invertida.
¿Has migrado a la nueva arquitectura? ¿Qué problemas encontraste?