Checklist de Regras de Projeto Expo
Vinte e cinco regras inegociáveis para aplicativos Expo de fácil manutenção no React Native 0.86 e Expo SDK 57. Estas regras cobrem o scaffolding do projeto, configuração, layout de pastas, Geração Nativa Contínua (CNG), higiene de dependências e convenções de equipe. Trate violações como bloqueadores de merge, a menos que um ADR documente uma exceção.
- Execute o Nível 1 ao fazer o scaffolding de um novo aplicativo ou imediatamente após uma atualização de SDK - erros de configuração e dependência se acumulam a cada sprint.
- Aplique os Níveis 2–4 durante a revisão de PR; arquivos de rota, pastas nativas e manipulação de segredos são as áreas de maior risco.
- Registre exceções intencionais em
docs/adr/ - "vamos consertar mais tarde" sem um ADR se torna dívida permanente.
- Revise o checklist completo trimestralmente e após cada grande atualização de SDK - os padrões do RN 0.86 e da Nova Arquitetura mudam o que significa "verde".
- Combine esta lista com as Melhores Práticas de Regras Expo para um resumo conciso de aplicação em reuniões diárias.
-
Fixe o SDK no momento do scaffold: Comece com npx create-expo-app@latest --template default@sdk-57 para que expo resolva para ~57.0.4 - atualizar três SDKs em um PR é uma fábrica de conflitos de merge.
- Verifique:
npx expo-doctor passa antes que o primeiro PR de funcionalidade seja mesclado.
- Rejeite:
latest sem um pin de SDK no CI ou na documentação de onboarding do README.
-
app.config.ts é a única fonte da verdade: A configuração dinâmica suporta ambientes, helpers tipados e plugins condicionais; um app.json estático isolado não escala além de um único flavor de build.
- Padrão: Exporte um
ExpoConfig tipado de app.config.ts e exclua campos duplicados em app.json.
- Audite:
npx expo config --type public antes de cada submissão para a loja.
-
Nunca comite segredos em extra ou EXPO_PUBLIC_*: Valores prefixados com EXPO_PUBLIC_ são inline no tempo de bundle - chaves de API, segredos de assinatura e tokens de administrador pertencem ao EAS Secrets, não ao git.
- Apenas não-segredos em tempo de execução: Passe flags de funcionalidade e URLs de API públicas via
extra e leia com Constants.expoConfig.
- Rejeite:
process.env.STRIPE_SECRET_KEY em qualquer lugar no código do aplicativo ou configuração.
-
Comite lockfiles com o aplicativo: package-lock.json, pnpm-lock.yaml ou yarn.lock devem corresponder ao que o EAS Build e o CI resolvem - instalações flutuantes escondem desvios nativos/JS até o TestFlight.
- CI: Falhe builds quando o lockfile estiver ausente ou fora de sincronia com
package.json.
- Monorepo: Um lockfile na raiz do workspace; aplicativos não mantêm árvores flutuantes independentes.
-
Use npx expo install para todos os pacotes Expo: npm install expo-camera@latest manual pode puxar stubs JS que não correspondem aos binários nativos do SDK 57 - TypeScript compila enquanto a produção falha.
- Caminho de atualização:
npx expo install --fix após atualizações de SDK, depois expo-doctor.
- Documente: Qualquer pacote que exija um override de versão personalizado recebe um ADR.
-
Mapeie perfis de build EAS para ambientes: Perfis eas.json declaram environment: development | preview | production para que credenciais e variáveis de ambiente se resolvam da mesma forma no CI e em laptops.
- Sincronização local:
eas env:pull --environment development para onboarding - não copiar e colar do Slack.
- Rejeite: URLs de API codificadas em fonte que diferem do perfil usado no EAS Build.
-
Diretório app/ fino: Arquivos do Expo Router reexportam telas de funcionalidades - a lógica de negócios, hooks e clientes de API não vivem ao lado de _layout.tsx.
- Padrão:
app/(tabs)/orders/index.tsx exporta OrdersScreen de features/orders.
- Lint: Regra ESLint opcional ou CODEOWNERS em
app/ para manter arquivos com ~20 linhas.
-
Organize por funcionalidade, não apenas por camada: features/orders/ possui telas, hooks, apresentadores e tipos específicos de funcionalidade - components/ global é apenas para primitivas do sistema de design.
- Rejeite: Árvores
screens/, hooks/ e services/ onde cada funcionalidade toca em cada pasta.
- Gatilho de escala: Revise com ~15 engenheiros antes que ciclos de importação forcem uma reescrita.
-
Uma exportação pública por funcionalidade: Arquivos de rota importam do barril features/orders - sem importações profundas entre funcionalidades em features/billing/hooks/useInvoice.ts.
- Aplique: Limites de módulos Nx ou uma regra ESLint personalizada
no-restricted-imports em monorepos.
- Exceção: APIs compartilhadas em
packages/core documentadas no README.
-
Mantenha scripts do package.json simples: start, ios, android, lint, typecheck, test - cada engenheiro não deve memorizar flags do Metro únicas.
- CI espelha o local: Os mesmos nomes de script são executados no GitHub Actions e nos hooks do EAS.
- Documente: Scripts não óbvios (
postinstall, eas-build-pre-install) no README.
-
Estenda expo/tsconfig.base: TypeScript rigoroso do template - desvios personalizados de tsconfig quebram rotas tipadas do Expo Router e tipos de autolinking.
- Paths: Espelhe aliases
@/* em moduleNameMapper do Jest ao usar aliases de caminho.
- Rejeite:
skipLibCheck: false entra em conflito com tipagens de RN de terceiros - siga os padrões do Expo.
-
Coloque os testes ao lado do código fonte: Button.test.tsx ao lado de Button.tsx ou em features/orders/__tests__/ - __tests__ distantes na raiz do repositório param de ser atualizados.
- Exclua: Mantenha os testes fora dos arquivos de rota
app/ - use __tests__ ou *.test.tsx em src/ e features/.
- CI:
npm test -- --ci em cada PR.
-
Ignore ios/ e android/ sob CNG: Pastas nativas commitadas de um SDK mais antigo bloqueiam os templates de prebuild do RN 0.86 - regenere no EAS Build ou npx expo prebuild --clean.
- Exceção Brownfield: Documente em ADR se pastas nativas forem intencionalmente commitadas.
- Ritual de atualização: Exclua pastas nativas obsoletas antes de
expo prebuild após atualizações de SDK.
-
Expresse mudanças nativas como plugins de configuração: Editar manualmente Info.plist ou AndroidManifest.xml gerados é perdido no npx expo prebuild --clean - o padrão do SDK 57.
- Plugins idempotentes: Seguros em execuções repetidas de prebuild - plugins que anexam duas vezes corrompem projetos.
- Veja: Regras de Módulos Nativos para quando código nativo personalizado é justificado.
-
Comece com Expo Go, passe para builds de desenvolvimento: Expo Go é bom para aprender; adicione expo-dev-client assim que depender de módulos nativos não incluídos no Expo Go.
- Regra de rebuild: Reconstrua o cliente de desenvolvimento após cada atualização de SDK - atualizações OTA mudam apenas JavaScript.
- CI: Um perfil EAS
development produz clientes de desenvolvimento instaláveis para QA.
-
Uma instância react-native no grafo de dependências: Cópias nativas duplicadas causam "Chamada de hook inválida" e obscurecem redboxes - npx expo-doctor e npm why react-native no CI.
- Monorepo:
npx expo install do diretório do aplicativo; eleve conscientemente com nodeLinker do pnpm.
- Rejeite:
node_modules/react-native aninhado de pacotes de workspace conflitantes.
-
Deixe o SDK 57 configurar o Metro primeiro: Detecção automática de monorepo supera watchFolders escritos manualmente - personalize apenas quando o doctor e os builds provarem uma lacuna.
- Documente: Qualquer mudança personalizada em
metro.config.js que link para a falha que ela corrige.
- Rejeite: Copiar e colar configuração do Metro de um post de blog pré-SDK-54.
-
Registre a raiz com registerRootComponent: Pontos de entrada bare ou brownfield que pulam a inicialização do Expo perdem a inicialização do autolinking e falham misteriosamente ao chamar módulos nativos.
- Verifique:
MainComponent / moduleName corresponde ao registro JS em embeds brownfield.
- Veja: Documentação da Plataforma Expo para
expo entrada em package.json main.
- Defina
owner para projetos de organização: Omitir "owner": "org-slug" em app.config roteia builds e credenciais para uma conta pessoal em vez da equipe.
- Um
projectId por binário de aplicativo: Reutilizar um projeto EAS entre IDs de aplicativo não relacionados colide credenciais e canais de atualização.
projectId estável: Nunca rotacione - serviços EAS dependem do UUID pela vida útil do aplicativo.
-
Tokens de robô para CI, não senhas pessoais: Usuários robôs com escopo de organização sobrevivem a saídas de funcionários e fornecem um caminho de revogação auditável.
- Escopo: Permissões mínimas por fluxo de trabalho - build, submit, update.
- Rejeite: Contas humanas compartilhadas "ci@company" com função de Proprietário.
-
Ignore .env.local, comite .env.example: Segredos específicos da máquina permanecem locais - o exemplo de env documenta as chaves EXPO_PUBLIC_* necessárias sem valores.
- Onboarding: README lista
eas env:pull como segundo passo após npm install.
- Rejeite:
.env.production com segredos reais no histórico do git.
-
Execute expo-doctor no CI em cada PR: Captura versões de módulos nativos incompatíveis, campos de configuração inválidos e desvios de dependência antes do merge.
- Branches de atualização: O Doctor deve passar antes que o PR de atualização de SDK seja mesclado - não como um ticket de acompanhamento.
- Combine com:
tsc --noEmit e expo lint.
-
Documente a verificação da primeira execução: Um script que executa expo-doctor, tsc --noEmit e opcionalmente um build de dev-client - novos contratados provam a toolchain em um comando.
- Nomeie:
npm run verify ou scripts/verify-toolchain.sh.
- Atualize: Após cada atualização de SDK, antes de anunciar "atualização concluída".
-
ADR para cada escolha arquitetural não padrão: Configuração Metro personalizada, pastas nativas commitadas, navegação não-Expo ou armazenamento seguro pulado - registre o contexto e a data de revisão.
-
Atualize SDKs sequencialmente: Pular múltiplas versões de SDK em um PR acumula mudanças que quebram - passe pelos changelogs entre merges, mesmo que o alvo final seja SDK 57.
- Leia: Notas do RN 0.86, Hermes, Reanimated e Nova Arquitetura antes de mesclar.
- Plano de rollback: Saiba qual build da loja e canal OTA promover se o branch de atualização falhar no QA.
- Nível 1 (1–6): Scaffold e configuração - corrija antes de escrever funcionalidades; um pin de SDK errado ou segredos vazados são caros para desfazer.
- Nível 2 (7–12): Layout e limites - evita telas gigantes e espaguete de importação à medida que o número de funcionários cresce.
- Nível 3 (13–18): Fluxo de trabalho nativo - custo mais alto quando violado; erros de prebuild e Metro bloqueiam lançamentos.
- Nível 4 (19–25): Governança e atualizações - trava convenções antes que a equipe dobre.
Devemos comitar as pastas ios/ e android/?
Não para aplicativos Expo CNG padrão - ignore-os e deixe o EAS Build ou expo prebuild regenerar. Aplicativos Brownfield com código nativo mantido manualmente são a exceção; documente essa escolha em um ADR.
app.json ou app.config.ts?
Prefira app.config.ts para qualquer aplicativo com mais de um ambiente. Mantenha um app.json mínimo apenas se a ferramenta exigir, mas evite duplicar campos em ambos os arquivos.
Quando o Expo Go é suficiente?
Para aprender, demonstrações e trabalho inicial de UI sem módulos nativos personalizados. Mude para expo-dev-client antes de integrar pagamentos, push, tarefas em segundo plano ou qualquer pacote não incluído no Expo Go.
Como aplicamos a regra da thin app/?
Revisão de código, max-lines ESLint opcional em app/**, e barris de funcionalidade dos quais as telas devem importar. Arquivos de rota devem ser lidos como um índice, não um romance.
O que pertence a EXPO_PUBLIC_ vs EAS Secrets?
EXPO_PUBLIC_* apenas para valores seguros para serem enviados no bundle do cliente (URLs de API públicas, chaves de analytics destinadas ao cliente). Segredos do servidor, chaves de assinatura e tokens de administrador permanecem no EAS Secrets e no código do lado do servidor.
Monorepos precisam de regras diferentes?
As mesmas regras se aplicam; adicione: um lockfile, uma instância react-native, npx expo install de cada diretório de aplicativo e aplicação de limites Nx ou Turborepo para importações entre funcionalidades.
Com que frequência devemos executar expo-doctor?
Em cada PR no CI, localmente após npm install, e obrigatoriamente antes de mesclar qualquer branch de atualização de SDK.
Podemos pular lockfiles em pacotes apenas de bibliotecas?
Aplicativos sempre comitam lockfiles. Pacotes internos do workspace consumidos apenas via workspace:* seguem o lockfile raiz - não flutue versões dentro de packages/ui.
Quais scripts todo aplicativo Expo deve ter?
No mínimo: start, alvos de plataforma (ios/android ou expo run:*), lint e typecheck. Adicione test assim que o Jest for configurado. O CI deve chamar os mesmos nomes que os desenvolvedores usam localmente.
Quando precisamos de um ADR em vez de uma nota no README?
Quando a escolha afeta código nativo, canais de lançamento, postura de segurança ou é difícil de reverter - módulos nativos personalizados, ios/ commitado, pinning de certificado ou pular expo-secure-store para tokens.
Como lidamos com aplicativos white-label?
Variantes app.config separadas por marca (APP_VARIANT), IDs de bundle distintos, projectId EAS separado por binário, packages/core compartilhado - não código de funcionalidade bifurcado por cliente.
A Nova Arquitetura muda essas regras de projeto?
Os padrões do RN 0.86 favorecem a Nova Arquitetura - as regras do projeto ainda se aplicam. Atualizações de SDK exigem a leitura de itens do changelog nativo; CNG e expo-doctor importam mais, não menos.
Qual é o portão mínimo de CI para um novo repositório Expo?
expo-doctor, tsc --noEmit, expo lint e testes unitários (jest --ci). Adicione EAS Build em main quando os módulos nativos excederem o Expo Go.
As funcionalidades devem importar de outras funcionalidades?
Apenas através de barris públicos ou pacotes compartilhados - nunca importe profundamente hooks internos de outra funcionalidade. Acoplamentos entre funcionalidades pertencem a packages/core com APIs explícitas.
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).