Práticas Recomendadas para React Native
Visão Geral
Guia de otimização de performance para aplicações React Native, cobrindo otimizações em JavaScript/React, Nativo (iOS/Android) e bundling. Baseado no "Ultimate Guide to React Native Optimization" da Callstack.
Quando Aplicar
Consulte estas diretrizes quando:
- Depurando UI lenta ou com jank/engasgos
- Investigando vazamentos de memória (JS ou nativos)
- Otimizando o tempo de inicialização do aplicativo (TTI)
- Reduzindo o tamanho do bundle ou do aplicativo
- Escrevendo módulos nativos (Turbo Modules)
- Profileando a performance do React Native
- Revisando código React Native em busca de performance
Notas de Segurança
- Trate os comandos de shell nestas referências como operações locais do desenvolvedor. Revise-os antes de executar, prefira ferramentas com versão fixa (pinned) e evite enviar scripts remotos diretamente para um shell.
- Trate bibliotecas e plugins de terceiros como dependências que ainda exigem controles normais de cadeia de suprimentos: fixe versões, verifique a proveniência e atualize através do seu processo de revisão padrão.
- Trate o carregamento remoto de chunks como entrega de artefatos primários apenas. Prefira chunks agrupados no aplicativo ou manifestos de release assinados; chunks hospedados devem vir de origens HTTPS confiáveis que você controla e ser fixados à versão atual do aplicativo.
Diretrizes Ordenadas por Prioridade
| Prioridade | Categoria | Impacto | Prefixo |
|---|---|---|---|
| 1 | FPS e Re-renderizações | CRÍTICO | js-* |
| 2 | Tamanho do Bundle | CRÍTICO | bundle-* |
| 3 | Otimização de TTI | ALTO | native-*, bundle-* |
| 4 | Performance Nativa | ALTO | native-* |
| 5 | Gerenciamento de Memória | MÉDIO-ALTO | js-*, native-* |
| 6 | Animações | MÉDIO | js-* |
Os rótulos de impacto são dicas de triagem: CRÍTICO primeiro, ALTO em seguida, MÉDIO quando as evidências apontarem para lá.
Referência Rápida
Fluxo de Trabalho de Otimização
Siga este ciclo para qualquer problema de performance: Medir → Otimizar → Remedir → Validar
- Medir: Capture métricas de baseline antes das alterações. Para problemas de runtime, prefira timeline de commits, contagem de re-renderizações, componentes lentos, decomposição dos commits mais pesados e startup/TTI quando disponível. Profundidade da árvore de componentes ou contagem de componentes são contexto opcional, não substitutos. Não recomende memoização, estado atômico ou alterações no compilador sem um problema medido de renderização ou FPS.
- Otimizar: Aplique a correção direcionada da referência relevante
- Remedir: Execute a mesma medição para obter métricas atualizadas
- Validar: Confirme a melhoria (ex.: FPS 45→60, TTI 3,2s→1,8s, bundle 2,1MB→1,6MB)
Se as métricas não melhoraram, reverta e tente a próxima correção sugerida.
Salvaguardas de Revisão
- Verifique as versões das bibliotecas antes de sugerir correções específicas de API. Exemplo: FlashList v2 deprecia
estimatedItemSize, então não sinalize como ausente. - Não sugira alterações de dependência de
useMemoouuseCallbacka menos que o comportamento esteja demonstravelmente incorreto ou a profileação mostre trabalho desperdiçado vinculado àquele valor. - Não relate closures obsoletas de forma especulativa. Mostre o caminho de leitura obsoleto, uma reprodução ou evidência do profiler antes de apontá-lo.
- Ao profilear um fluxo, meça a interação alvo em si. Não trate a profundidade da árvore de componentes ou a contagem de componentes como a principal evidência de performance.
Crítico: FPS e Re-renderizações
Profile primeiro:
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
Conduza a interação alvo com comandos normais do agent-device entre profile start e profile stop.
Alternativa manual quando agent-device não estiver disponível: abra o React Native DevTools a partir do Metro (j) ou do Menu de Desenvolvimento, use a aba Profiler e registre a mesma interação.
Para profileação de componentes React em builds de release, conecte @callstack/inspector primeiro para que o React DevTools possa anexar ao aplicativo de release, então execute o fluxo agent-device react-devtools acima.
Correções comuns:
- Substitua ScrollView por FlatList/FlashList/Legend List para listas longas
- Após profileação mostrar re-renderizações em cascata, use o React Compiler para memoização automática
- Após profileação mostrar amplas atualizações de store/contexto, use estado atômico (Jotai/Zustand) para reduzir re-renderizações
- Use
useDeferredValuepara computações caras
Crítico: Tamanho do Bundle
Analise o 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 a melhoria após a otimização:
# Registre o tamanho baseline antes das alterações
ls -lh output.js # Ex.: Antes: 2.1 MB
# Após aplicar correções, re-empacote e compare
npx react-native bundle --entry-file index.js --bundle-output output.js \
--platform ios --dev false --minify true
ls -lh output.js # Ex.: Depois: 1.6 MB (redução de 24%)
Correções comuns:
- Evite imports barrel (importe diretamente da fonte)
- Remova polyfills Intl desnecessários somente após verificar a cobertura de API e métodos do Hermes
- Avalie tree shaking (remoção experimental de imports/exports não utilizados do Expo SDK 52+ ou Re.Pack apenas se já configurado)
- Ative R8 para redução de código nativo Android
Alto: Otimização de TTI
Meça o TTI:
- Use
react-native-performancepara marcadores - Meça apenas partidas a frio (exclua warm/hot/prewarm)
Correções comuns:
- Para React Native 0.78 e anteriores, desabilite a compressão do bundle JS no Android para habilitar mmap do Hermes
- Use navegação nativa (react-native-screens)
- Pré-carregue telas caras comumente usadas antes de navegar para elas
Alto: Performance Nativa
Profile nativo:
- iOS: Xcode Instruments → Time Profiler
- Android: Android Studio → CPU Profiler
Correções comuns:
- Use threads em segundo plano para trabalho nativo pesado
- Prefira métodos Turbo Module assíncronos em vez de síncronos
- Use C++ para código crítico de performance multiplataforma
Referências
Documentação completa com exemplos de código em references/:
JavaScript/React (js-*)
| Arquivo | Impacto | Descrição |
|---|---|---|
| js-lists-flatlist-flashlist.md | CRÍTICO | Substitua ScrollView por listas virtualizadas |
| js-profile-react.md | MÉDIO | Profileação com agent-device react-devtools |
| js-measure-fps.md | ALTO | Monitoramento e medição de FPS |
| js-memory-leaks.md | MÉDIO | Caça a vazamentos de memória JS |
| js-atomic-state.md | ALTO | Padrões Jotai/Zustand |
| js-concurrent-react.md | ALTO | useDeferredValue, useTransition |
| js-react-compiler.md | ALTO | Memoização automática |
| js-animations-reanimated.md | MÉDIO | Worklets do Reanimated |
| js-bottomsheet.md | ALTO | Otimização de bottom sheet |
| js-uncontrolled-components.md | ALTO | Otimização de TextInput |
Nativo (native-*)
| Arquivo | Impacto | Descrição |
|---|---|---|
| native-turbo-modules.md | ALTO | Construindo módulos nativos rápidos |
| native-sdks-over-polyfills.md | ALTO | Bibliotecas nativas vs JS |
| native-measure-tti.md | ALTO | Configuração de medição de TTI |
| native-threading-model.md | ALTO | Threads de Turbo Module |
| native-profiling.md | MÉDIO | Profileação com Xcode/Android Studio |
| native-platform-setup.md | MÉDIO | Guia de ferramentas para iOS/Android |
| native-view-flattening.md | MÉDIO | Depuração de hierarquia de views |
| native-memory-patterns.md | MÉDIO | Memória em C++/Swift/Kotlin |
| native-memory-leaks.md | MÉDIO | Caça a vazamentos de memória nativos |
| native-android-16kb-alignment.md | CRÍTICO | Alinhamento de bibliotecas de terceiros para Google Play |
Bundling (bundle-*)
| Arquivo | Impacto | Descrição |
|---|---|---|
| bundle-barrel-exports.md | CRÍTICO | Evite imports barrel |
| bundle-analyze-js.md | CRÍTICO | Visualização do bundle JS |
| bundle-tree-shaking.md | ALTO | Eliminação de código morto |
| bundle-analyze-app.md | ALTO | Análise de tamanho do aplicativo |
| bundle-r8-android.md | ALTO | Redução de código Android |
| bundle-hermes-mmap.md | ALTO | Desabilitar compressão do bundle |
| bundle-native-assets.md | ALTO | Configuração do catálogo de assets |
| bundle-library-size.md | MÉDIO | Avaliar dependências |
| bundle-code-splitting.md | MÉDIO | Salvaguardas para carregamento remoto de chunks |
Mapeamento Problema → Skill
| Problema | Comece Com |
|---|---|
| Aplicativo parece lento/engasgado | js-measure-fps.md → js-profile-react.md |
| Muitas re-renderizações | js-profile-react.md → js-react-compiler.md |
| Inicialização lenta (TTI) | native-measure-tti.md → bundle-analyze-js.md |
| Tamanho do aplicativo grande | bundle-analyze-app.md → bundle-r8-android.md |
| Memória crescendo | js-memory-leaks.md ou native-memory-leaks.md |
| Animação perdendo quadros | js-animations-reanimated.md |
| Bottom sheet com jank/re-renderizações | js-bottomsheet.md → js-animations-reanimated.md |
| Rolamento de lista com jank | js-lists-flatlist-flashlist.md |
| Lag em TextInput | js-uncontrolled-components.md |
| Módulo nativo lento | native-turbo-modules.md → native-threading-model.md |
| Problema de alinhamento de biblioteca nativa | native-android-16kb-alignment.md |
Atribuição
Baseado em "The Ultimate Guide to React Native Optimization" da Callstack.