Regras de Orçamento de Desempenho
Tamanho do bundle, tempo para interatividade (TTI) e limites de taxa de quadros com proprietários nomeados para aplicativos Expo SDK 57 no React Native 0.86. Orçamentos de desempenho transformam "parece lento" subjetivo em portões de merge e lançamento. Atribua proprietários - orçamentos anônimos são ignorados.
- Defina orçamentos Nível 1 durante o pontapé inicial do projeto - adaptar limites após 200 telas é politicamente mais difícil do que tecnicamente.
- Nível 2 é executado em CI em todo PR que toca dependências, listas ou caminho de inicialização.
- Nível 3 é auditoria manual em dispositivo antes da submissão para loja e promoções importantes de OTA.
- Quando um orçamento é excedido, exija uma exceção ADR ou uma correção - isenções expiram no próximo lançamento.
- Dispositivo de medição padrão: Android de gama média (por exemplo, classe Pixel 6a) mais um iPhone SE mais antigo - não o Pro Max do líder.
| Métrica | Limite (inicial) | Cargo do proprietário |
|---|
| Bundle JS principal (Hermes) | ≤ 4 MB gzipped | Líder da plataforma móvel |
| Download total (atualização OTA) | ≤ 8 MB | Engenheiro de lançamento |
| TTI de inicialização fria (aba principal) | ≤ 2.5 s no Android de referência | Líder da equipe de recursos |
| FPS de rolagem (lista principal) | ≥ 55 fps sustentados | Campeão de desempenho de UI |
| Memória após 10 min de sessão | ≤ 350 MB no Android de referência | Plantão móvel |
Ajuste os números por categoria de aplicativo - documente seus limites em docs/performance-budgets.md e link de README.
-
Publique orçamentos escritos antes do feature freeze: MB do bundle, segundos de TTI, limites de FPS e tetos de memória - a tabela inicial acima é um modelo, não uma lei universal.
- Proprietário: Cada métrica tem uma pessoa nomeada, não "a equipe".
- Revisão: Trimestralmente ou quando o MAU dobrar.
-
Escolha dispositivos de referência e versões de SO: Um Android de gama média e um dispositivo iOS mais antigo - todas as auditorias usam o mesmo pool de hardware.
- CI não pode substituir: Laboratório de dispositivos ou rotação de engenheiros para auditoria pré-lançamento.
- Rejeitar: "Funciona no meu iPhone 16 Pro" como aprovação.
-
Defina a medição de TTI: Inicialização fria → primeiro frame interativo na aba principal de receita (por exemplo, botão de envio do feed inicial habilitado).
- Instrumente:
performance.mark no layout raiz e onLayout da tela, ou API de Desempenho do React Native.
- Exclua: Tempos do cliente de desenvolvimento e Fast Refresh dos orçamentos de produção.
-
Defina o escopo do bundle: Bundle principal do Hermes + chunks lazy carregados antes do TTI - documente quais divisões assíncronas contam para o orçamento de primeira abertura.
- Ferramenta:
npx react-native bundle com --verbose ou análise de exportação do Expo.
- OTA: Limite de tamanho de atualização de produção separado do tamanho de instalação.
-
Vincule regressões à política de rollback: Regressão de bundle ou TTI além de X% aciona consideração de rollback das Regras de Lançamento e OTA.
- X: Frequentemente 10% relativo ou estouro absoluto fixo.
- Comunique: O plantão sabe dos gatilhos de desempenho junto com os gatilhos de crash.
-
ADR para exceções permanentes de orçamento: Aplicativos pesados de mapas offline ou vídeo podem precisar de tetos mais altos - documente o valor do usuário e a mitigação (carregamento lazy, download sob demanda).
-
Verificação de tamanho do bundle Hermes em CI: Script compara o bundle exportado com o limite - falha o PR quando acima do orçamento sem aprovação de rótulo perf-budget.
- Proprietário: Plataforma móvel mantém o script em
scripts/check-bundle-size.sh.
- Linha de base: Atualize a linha de base apenas com ADR, não com aumentos silenciosos de PR.
-
Revisão de tamanho de dependência em adições nativas e JS: npx expo install novo pacote → verifique o custo de importação e o impacto no tamanho do binário nativo.
- Prefira: Importações por função de
date-fns, subconjuntos de lodash-es.
- Rejeite: Bibliotecas de data duplicadas, moment.js, lodash completo.
-
Sem novo require síncrono no caminho de inicialização: Adie módulos pesados com import() em abas não críticas - grep require( em app/_layout.tsx e provedores raiz.
- Cheiro: Importar biblioteca de gráficos inteira no layout raiz.
- Correção: Importação lazy no nível da tela com esqueleto.
-
Orçamentos de imagem e fonte: WebP/AVIF onde suportado; fontes subsetadas via expo-font - no máximo duas famílias de fontes no caminho crítico.
- Proprietário: Líder do sistema de design aprova novos pesos.
- Rejeite: PNG de fundo de 800 KB quando existe WebP comprimido.
-
Lint de desempenho de lista na revisão: FlatList / FlashList requer keyExtractor, componente renderItem estável e linhas memoizadas - sem hooks dentro de renderItem.
- Veja: Regras de lint do React Hooks para violações de hooks em
renderItem.
- Meça: Flashlight ou monitor de desempenho RN na tela de lista mais longa.
-
Worklets Reanimated e gesture permanecem fora da thread JS: Animações que perdem quadros acionam investigação antes do merge - profile com react-native-performance.
- Orçamento: Animações de interação ≤ 300 ms para estado estável.
- Rejeite:
LayoutAnimation em listas com mais de 500 linhas.
-
TTI de inicialização fria no Android de referência a cada RC: Registre a mediana de 5 inicializações frias - compare com o último RC e o orçamento.
- Proprietário: Engenheiro de lançamento registra no ticket de lançamento.
- Bloqueie: Promoção de RC se o TTI regredir > 15% sem isenção.
-
FPS de rolagem na tela de lista principal: Passe o teste por 50 itens - limite de fps sustentado (55+) no dispositivo de referência.
- Ferramenta: Overlay do monitor de desempenho ou amostra Systrace.
- Correção:
FlashList, componentes de linha menores, correções de tamanho de imagem.
-
Snapshot de memória após 10 minutos de sessão roteirizada: Navegue por abas, abra detalhes, retorne - heap estável sem aumento indicando vazamentos.
- Proprietário: Plantão móvel revisa suspeitos de vazamento.
- Nativo: Libere handles
SharedObject de módulos Expo ao desmontar.
-
Tamanho do download da atualização OTA antes da publicação em produção: Tamanho do artefato eas update - avise quando acima do orçamento OTA.
- Comprima: Assets via pipeline
expo-asset; deduplique imagens.
- Rollback: OTA grande correlaciona-se com atualizações lentas e rotatividade de usuários.
-
Waterfall de rede na tela principal: Paralelize requisições independentes; evite cadeias await seriais que bloqueiam a pintura.
- Padrão: Consultas paralelas TanStack Query na montagem da tela.
- Orçamento: Primeira resposta de API de conteúdo < 800 ms p95 em staging.
-
Verificação pontual de bateria e térmica: Sessão de navegação de 15 minutos - o dispositivo não deve desacelerar severamente no Android de referência.
- Cheiro: Polling de localização a cada segundo em segundo plano.
- Correção: Agrupe watchers; use localização de mudança significativa quando possível.
-
Rótulo de PR de desempenho: Mudanças que tocam listas, imagens, inicialização ou dependências > 50 KB exigem perf-review do proprietário do orçamento.
- Bot: Regras de rótulo do GitHub de caminhos CODEOWNERS.
- Educação: Revisores vinculam à métrica falha, não a um vago "otimize isso".
-
Dashboard semanal: TTI, sem crashes, amostragem de FPS (se RUM disponível), tendência de tamanho do bundle - visível para produto e engenharia.
- Proprietário: Plataforma móvel posta snapshot em #mobile.
- Alerta: Postagem automática de regressão semana a semana.
-
Verificação da Nova Arquitetura na atualização: A Nova Arquitetura do RN 0.86 pode mudar as características de desempenho - re-baseline após atualizações de SDK.
- Compare: Mesmos dispositivos de referência antes/depois da atualização.
- Documente: Achados no ADR de atualização do SDK.
-
Flags de recursos para experimentos de desempenho: Lance scroll infinito ou novo pipeline de imagem para 5% antes do OTA completo - observe métricas RUM.
-
Sem tickets de débito de desempenho sem métrica: "Tornar o aplicativo mais rápido" não é um ticket - "Reduzir TTI da home de 3.1s para 2.5s no Pixel 6a" é.
- Concluído: Melhoria medida anexada ao PR.
- Rejeite: Memoização prematura sem profiling.
-
Apêndice de desempenho para submissão na loja: Ticket de lançamento inclui TTI, tamanho do bundle, resultados da auditoria de FPS e links de ADR de isenção - aprovação de QA referencia os números.
- Apple: Observe violações da thread principal em Instruments antes da submissão iOS.
- Google: Vitais do Android monitorados após o lançamento.
- Nível 1 (1–6): Defina orçamentos e proprietários - sem números, nada é aplicável.
- Nível 2 (7–12): Automatize em CI - capture regressões no momento do PR.
- Nível 3 (13–18): Auditoria em dispositivo - simuladores e iPhones Pro mentem.
- Nível 4 (19–24): Processo - mantém os orçamentos vivos após o primeiro sprint.
Qual é um orçamento razoável de bundle JS para Expo SDK 57?
Muitos aplicativos de consumo visam um bundle principal Hermes gzipped de 3–5 MB no TTI. Aplicativos pesados (mapas, vídeo) precisam de tetos mais altos com justificativa ADR. Meça sua linha de base antes de copiar um número.
Por que medir em Android de gama média?
Android de baixo custo expõe travamentos, pressão de memória e armazenamento lento que iPhones de ponta escondem. Se passar em Android de gama média, o iOS geralmente fica bem; o inverso é falso.
Como medir TTI em React Native?
Marque o lançamento do aplicativo no _layout.tsx raiz, marque interativo quando a tela principal terminar o layout e o portão de dados abrir. Use a API de Desempenho ou eventos de análise personalizados - exclua builds de cliente de desenvolvimento.
OTA afeta o orçamento do bundle?
Sim - cada atualização tem um orçamento de tamanho de download. Grandes bundles OTA atrasam atualizações e aumentam as taxas de falha. Verifique o tamanho do artefato antes do eas update de produção.
FlashList ou FlatList?
Use FlashList por padrão para listas longas e heterogêneas no SDK 57. FlatList é bom para listas estáticas curtas. O proprietário do orçamento revisa as mudanças na lista nos feeds principais.
O CI pode medir FPS?
Raramente de forma confiável - a auditoria de FPS permanece manual ou baseada em RUM. CI se destaca em tamanho de bundle e verificações de dependência; o laboratório de dispositivos cobre os frames.
O que aciona um rollback de desempenho?
Definido pela equipe - geralmente regressão de TTI > 15%, aumento de crashes ou estouro de bundle ligado a crashes de inicialização. Documente os gatilhos na tabela de Regras de Lançamento e OTA.
Imagens em expo-asset contam para o bundle?
Sim, se empacotadas no momento da compilação. Prefira assets de tamanho apropriado, formatos modernos e CDN remoto para mídia raramente usada.
Como a Nova Arquitetura afeta os orçamentos?
Fabric pode melhorar o desempenho de rolagem de listas, mas pode mudar a memória - re-baseline após habilitá-lo no RN 0.86. Não assuma números idênticos à Arquitetura Antiga.
Quem aprova a isenção de orçamento?
O proprietário nomeado para essa métrica mais o líder móvel. O ADR de isenção inclui a versão de lançamento de expiração e o plano de mitigação.
Devemos fazer profiling em produção?
Sim, com RUM amostrado (Sentry performance, análises personalizadas) - respeite a privacidade, sem PII em eventos de desempenho. Staging espelha a arquitetura de produção para mergulhos profundos.
E os benchmarks do Expo Go?
Expo Go inclui sobrecarga extra - nunca use para aprovação de orçamento. Use builds EAS de preview ou profile de produção em dispositivos de referência.
Como monorepos atribuem o tamanho do bundle?
Meça por exportação de aplicativo de apps/mobile. Pacotes compartilhados contam para cada aplicativo que os importa - imponha limites de pacotes para evitar importações acidentais de bloat.
Versões da Stack: Esta página foi escrita para React 19.2.3, React Native 0.86.0 e Expo SDK 57 (expo ~57.0.4).