Mejores Prácticas de React Native
Resumen
Guía de optimización de rendimiento para aplicaciones React Native, que cubre optimizaciones de JavaScript/React, nativas (iOS/Android) y de empaquetado. Basada en la 'Guía Definitiva para la Optimización de React Native' de Callstack.
Cuándo Aplicar
Consulte estas pautas cuando:
- Depure una UI lenta o con tirones, o animaciones.
- Investigue fugas de memoria (JS o nativas).
- Optimice el tiempo de inicio de la aplicación (TTI).
- Reduzca el tamaño del bundle o de la aplicación.
- Escriba módulos nativos (Turbo Modules).
- Perfile el rendimiento de React Native.
- Revise código React Native en busca de rendimiento.
Notas de Seguridad
- Trate los comandos de shell en estas referencias como operaciones de desarrollador local. Revíselos antes de ejecutarlos, prefiera herramientas con versiones fijas y evite canalizar scripts remotos directamente a un shell.
- Trate las bibliotecas y complementos de terceros como dependencias que aún requieren controles normales de la cadena de suministro: fije versiones, verifique la procedencia y actualice a través de su proceso de revisión estándar.
- Trate la carga de chunks remotos como entrega de artefactos internos únicamente. Prefiera chunks empaquetados en la aplicación o manifiestos de lanzamiento firmados por CI; los chunks alojados deben provenir de orígenes HTTPS confiables que usted controle y estar fijados a la versión actual de la aplicación.
Pautas Ordenadas por Prioridad
| Prioridad | Categoría | Impacto | Prefijo |
|---|---|---|---|
| 1 | FPS y Re-renderizados | CRÍTICO | js-* |
| 2 | Tamaño del Bundle | CRÍTICO | bundle-* |
| 3 | Optimización TTI | ALTO | native-*, bundle-* |
| 4 | Rendimiento Nativo | ALTO | native-* |
| 5 | Gestión de Memoria | MEDIO-ALTO | js-*, native-* |
| 6 | Animaciones | MEDIO | js-* |
Las etiquetas de impacto son indicaciones de clasificación: CRÍTICO primero, ALTO después, MEDIO cuando la evidencia apunte allí.
Referencia Rápida
Flujo de Trabajo de Optimización
Siga este ciclo para cualquier problema de rendimiento: Medir → Optimizar → Volver a medir → Validar
- Medir: Capture métricas de referencia antes de los cambios. Para problemas en tiempo de ejecución, prefiera la línea de tiempo de commits, conteos de re-renderizados, componentes lentos, desglose de commit más pesado e inicio/TTI cuando estén disponibles. La profundidad o el conteo de componentes del árbol son contexto opcional, no sustitutos. No recomiende memoización, estado atómico o cambios de compilador sin un problema de renderizado o FPS medido.
- Optimizar: Aplique la corrección específica de la referencia relevante.
- Volver a medir: Ejecute la misma medición para obtener métricas actualizadas.
- Validar: Confirme la mejora (p. ej., FPS 45→60, TTI 3.2s→1.8s, bundle 2.1MB→1.6MB).
Si las métricas no mejoraron, revierta e intente la siguiente corrección sugerida.
Barreras de Revisión
- Verifique las versiones de las bibliotecas antes de sugerir correcciones específicas de la API. Ejemplo: FlashList v2 depreca
estimatedItemSize, por lo que no lo marque como faltante allí. - No sugiera cambios de dependencia
useMemoouseCallbacka menos que el comportamiento sea demostrablemente incorrecto o la creación de perfiles muestre trabajo desperdiciado vinculado a ese valor. - No informe closures obsoletos de forma especulativa. Muestre la ruta de lectura obsoleta, una reproducción o evidencia del perfilador antes de señalarlo.
- Al perfilar un flujo, mida la interacción objetivo en sí misma. No trate la profundidad del árbol de componentes o el conteo de componentes como la principal evidencia de rendimiento.
Crítico: FPS y Re-renderizados
Perfile primero:
agent-device react-devtools status
agent-device react-devtools wait --connected
agent-device react-devtools profile start
agent-device react-devtools profile stop
agent-device react-devtools profile slow --limit 5
agent-device react-devtools profile rerenders --limit 5
agent-device react-devtools profile timeline --limit 20
Conduzca la interacción objetivo con comandos normales de agent-device entre profile start y profile stop.
Alternativa manual cuando agent-device no esté disponible: abra React Native DevTools desde Metro (j) o el Menú de Desarrollador, use la pestaña Profiler y registre la misma interacción.
Para la creación de perfiles de componentes React en build de release, conecte primero @callstack/inspector para que React DevTools pueda conectarse a la aplicación de release, luego ejecute el flujo agent-device react-devtools anterior.
Correcciones comunes:
- Reemplace ScrollView con FlatList/FlashList/Legend List para listas largas.
- Después de que la creación de perfiles muestre re-renderizados en cascada, use React Compiler para la memoización automática.
- Después de que la creación de perfiles muestre actualizaciones amplias de store/contexto, use estado atómico (Jotai/Zustand) para reducir los re-renderizados.
- Use
useDeferredValuepara cálculos costosos.
Crítico: Tamaño del Bundle
Analice el bundle:
npx react-native bundle \
--entry-file index.js \
--bundle-output output.js \
--platform ios \
--sourcemap-output output.js.map \
--dev false --minify true
npx source-map-explorer output.js --no-border-checks
Verifique la mejora después de la optimización:
# Registre el tamaño de referencia antes de los cambios
ls -lh output.js # p. ej., Antes: 2.1 MB
# Después de aplicar correcciones, re-empaquete y compare
npx react-native bundle --entry-file index.js --bundle-output output.js \
--platform ios --dev false --minify true
ls -lh output.js # p. ej., Después: 1.6 MB (reducción del 24%)
Correcciones comunes:
- Evite importaciones tipo barril (importe directamente desde el origen).
- Elimine polyfills Intl innecesarios solo después de verificar la cobertura de API y métodos de Hermes.
- Evalúe la eliminación de código muerto (Expo SDK 52+ eliminación experimental de importaciones/exportaciones no usadas, o Re.Pack solo si ya está configurado).
- Habilite R8 para la reducción de código nativo en Android.
Alto: Optimización TTI
Mida TTI:
- Use
react-native-performancepara marcadores. - Solo mida arranques en frío (excluya arranques en caliente/tibio/precalentado).
Correcciones comunes:
- Para React Native 0.78 y versiones anteriores, deshabilite la compresión del bundle JS de Android para habilitar mmap de Hermes.
- Use navegación nativa (react-native-screens).
- Precargue pantallas costosas de uso común antes de navegar a ellas.
Alto: Rendimiento Nativo
Perfile nativo:
- iOS: Xcode Instruments → Time Profiler
- Android: Android Studio → CPU Profiler
Correcciones comunes:
- Use hilos en segundo plano para trabajo nativo pesado.
- Prefiera métodos de Turbo Module asíncronos sobre síncronos.
- Use C++ para código crítico de rendimiento multiplataforma.
Referencias
Documentación completa con ejemplos de código en references/:
JavaScript/React (js-*)
| Archivo | Impacto | Descripción |
|---|---|---|
| js-lists-flatlist-flashlist.md | CRÍTICO | Reemplace ScrollView con listas virtualizadas |
| js-profile-react.md | MEDIO | Creación de perfiles con agent-device react-devtools |
| js-measure-fps.md | ALTO | Monitoreo y medición de FPS |
| js-memory-leaks.md | MEDIO | Búsqueda de fugas de memoria en JS |
| js-atomic-state.md | ALTO | Patrones con Jotai/Zustand |
| js-concurrent-react.md | ALTO | useDeferredValue, useTransition |
| js-react-compiler.md | ALTO | Memoización automática |
| js-animations-reanimated.md | MEDIO | Worklets de Reanimated |
| js-bottomsheet.md | ALTO | Optimización de bottom sheets |
| js-uncontrolled-components.md | ALTO | Optimización de TextInput |
Nativo (native-*)
| Archivo | Impacto | Descripción |
|---|---|---|
| native-turbo-modules.md | ALTO | Construcción de módulos nativos rápidos |
| native-sdks-over-polyfills.md | ALTO | Bibliotecas nativas vs JS |
| native-measure-tti.md | ALTO | Configuración de medición de TTI |
| native-threading-model.md | ALTO | Hilos de Turbo Module |
| native-profiling.md | MEDIO | Creación de perfiles con Xcode/Android Studio |
| native-platform-setup.md | MEDIO | Guía de herramientas para iOS/Android |
| native-view-flattening.md | MEDIO | Depuración de jerarquía de vistas |
| native-memory-patterns.md | MEDIO | Memoria en C++/Swift/Kotlin |
| native-memory-leaks.md | MEDIO | Búsqueda de fugas de memoria nativas |
| native-android-16kb-alignment.md | CRÍTICO | Alineación de bibliotecas de terceros para Google Play |
Empaquetado (bundle-*)
| Archivo | Impacto | Descripción |
|---|---|---|
| bundle-barrel-exports.md | CRÍTICO | Evite importaciones tipo barril |
| bundle-analyze-js.md | CRÍTICO | Visualización del bundle JS |
| bundle-tree-shaking.md | ALTO | Eliminación de código muerto |
| bundle-analyze-app.md | ALTO | Análisis del tamaño de la aplicación |
| bundle-r8-android.md | ALTO | Reducción de código en Android |
| bundle-hermes-mmap.md | ALTO | Desactivar compresión del bundle |
| bundle-native-assets.md | ALTO | Configuración del catálogo de recursos |
| bundle-library-size.md | MEDIO | Evaluar dependencias |
| bundle-code-splitting.md | MEDIO | Salvaguardas de carga de chunks remotos |
Mapeo Problema → Habilidad
| Problema | Empezar con |
|---|---|
| La aplicación se siente lenta/con tirones | js-measure-fps.md → js-profile-react.md |
| Demasiados re-renderizados | js-profile-react.md → js-react-compiler.md |
| Inicio lento (TTI) | native-measure-tti.md → bundle-analyze-js.md |
| Tamaño grande de la aplicación | bundle-analyze-app.md → bundle-r8-android.md |
| La memoria crece | js-memory-leaks.md o native-memory-leaks.md |
| La animación pierde fotogramas | js-animations-reanimated.md |
| Bottom sheet con tirones/re-renderizados | js-bottomsheet.md → js-animations-reanimated.md |
| Desplazamiento de lista con tirones | js-lists-flatlist-flashlist.md |
| Lag en TextInput | js-uncontrolled-components.md |
| Módulo nativo lento | native-turbo-modules.md → native-threading-model.md |
| Problema de alineación de biblioteca nativa | native-android-16kb-alignment.md |
Atribución
Basado en 'The Ultimate Guide to React Native Optimization' de Callstack.