Regras de Módulos Nativos
Quando escrever código nativo em vez de procurar um pacote do SDK do Expo. Estas regras mantêm as equipes no caminho suportado para o Expo SDK 57 e React Native 0.86, minimizam surpresas com CNG/prebuild e garantem que as dependências nativas sejam enviadas com binários de cliente de desenvolvimento e da loja correspondentes.
- Percorra a Tier 1 antes de adicionar qualquer pacote npm com código nativo - a dependência errada força uma reconstrução do cliente de desenvolvimento e pode bloquear o Expo Go inteiramente.
- Aplique as Tiers 2–3 ao integrar plugins de configuração ou escrever módulos nativos personalizados - erros corrompem
ios/ e android/ em cada prebuild.
- Execute a Tier 4 antes de mesclar alterações nativas - o CI deve provar que o prebuild é reproduzível e que a compilação da Nova Arquitetura ainda compila.
- Cada módulo nativo personalizado precisa de um ADR com um proprietário nomeado - código nativo órfão se torna irremovível.
- Use em conjunto com
npx expo-doctor após cada alteração de dependência nativa.
-
Pesquise pacotes do SDK do Expo primeiro: expo-camera, expo-location, expo-notifications e mais de 100 módulos são enviados com binários nativos do SDK 57 - prefira-os em vez de wrappers nativos aleatórios do npm.
- Instalar:
npx expo install expo-camera - não npm install expo-camera@latest.
- Verificar: O pacote aparece na documentação do Expo para o SDK 57 antes de adotá-lo.
-
Segunda opção: módulo da comunidade com plugin de configuração do Expo: Muitas bibliotecas enviam um plugin de configuração na matriz plugins do app.config - leia a matriz de compatibilidade do SDK 57 antes de instalar.
- Verificar: Issues do GitHub para suporte a RN 0.86 e Nova Arquitetura.
- Rejeitar: Módulos não mantidos atualizados pela última vez para o SDK 49.
-
Terceira opção: API de Módulos do Expo para pontes nativas finas: Quando nenhum pacote existe, escreva um módulo Expo em modules/my-feature/ - autolinking e tipos TypeScript integram-se perfeitamente com CNG.
- Template:
npx create-expo-module@latest para o scaffold do módulo.
- ADR necessário: Documente por que os pacotes do SDK foram insuficientes.
-
Último recurso: patches nativos Swift/Kotlin via plugin de configuração: Pastas ios/ e android/ mantidas manualmente são apenas para brownfield - aplicativos CNG padrão expressam alterações como plugins.
- Brownfield: ADR explica por que o CNG não é usado.
- Rejeitar: Edições de "correção rápida" em
Podfile que não estão codificadas em um plugin.
-
Expo Go não é um alvo de teste nativo para módulos personalizados: Pacotes não incluídos no Expo Go exigem expo-dev-client - não reivindique aprovação de QA apenas do Expo Go.
- CI: O perfil EAS
development cria clientes de desenvolvimento instaláveis.
- Onboarding: O README declara as limitações do Expo Go no primeiro dia.
-
Uma alteração nativa por PR, quando possível: Misturar um novo SDK de pagamento, plugin de câmera e módulo personalizado em um único merge torna o bisect impossível quando o prebuild falha.
- Rollback: PRs de propósito único mapeiam claramente para decisões de rollback da loja e OTA.
- Revisão: Alterações nativas recebem um revisor dedicado com experiência em plataforma móvel.
-
Sempre use npx expo install para dependências nativas: Resolve versões compatíveis com os binários nativos do SDK 57 - o sucesso da compilação não garante estabilidade em tempo de execução.
- Após o bump do SDK:
npx expo install --fix e depois expo-doctor.
- CI: Falhe se os intervalos do
package.json se desviarem das versões empacotadas do Expo sem ADR.
-
Registre plugins de configuração em app.config.ts: Permissões nativas, entitlements e entradas de manifesto pertencem a plugins - não a edições manuais pós-prebuild.
- Ordem: A ordem dos plugins importa quando vários plugins tocam no mesmo arquivo - documente a ordem nos comentários.
- Inspecione:
npx expo prebuild --clean localmente antes de mesclar alterações de plugin.
-
Escreva plugins de configuração idempotentes: Executar prebuild duas vezes não deve duplicar entradas em Info.plist ou AndroidManifest.xml.
- Teste: Execute o prebuild duas vezes e use
git diff na saída nativa - deve estar vazio na segunda vez.
- Rejeitar: Plugins de anexar com Regex sem verificações de existência.
-
Declare permissões com strings voltadas para o usuário: iOS NSCameraUsageDescription e rationale de permissão do Android - strings ausentes travam ou rejeitam a revisão da loja.
- Fonte: Plugin ou
app.config ios.infoPlist - nunca apenas em arquivos gerados.
- Localização: Planeje
locales/ para strings de permissão nos idiomas publicados.
-
Use expo-build-properties para SDK de compilação e alvos de implantação: Centralize minSdkVersion, compileSdkVersion e o alvo de implantação do iOS - edições dispersas do Gradle são perdidas no prebuild.
- Padrões do SDK 57: Comece com os padrões do Expo; substitua apenas com necessidade medida.
- ADR: Documente por que a versão mínima do sistema operacional foi aumentada.
-
Autolinking lida com a maioria dos links - não edite manualmente settings.gradle: O autolinking do Expo registra módulos nativos - hacks manuais de pod install pertencem a plugins, se verdadeiramente necessários.
- Depurar:
npx expo-modules-autolinking resolve quando um módulo não é encontrado.
- Monorepo: Garanta uma única instância de
react-native - cópias duplicadas quebram o autolinking silenciosamente.
-
Gitignore ios/ e android/ gerados sob CNG: Pastas nativas commitadas bloqueiam atualizações de template do SDK 57 - o EAS Build executa o prebuild remotamente.
- Depuração local:
npx expo prebuild --clean reproduz projetos nativos do CI.
- Exceção: ADR de Brownfield com estratégia de merge para diretórios nativos.
-
Reconstrua o cliente de desenvolvimento após cada alteração de dependência nativa: Atualizações OTA (eas update) atualizam apenas JavaScript - novos módulos nativos exigem eas build --profile development.
- Comunique: Poste em #mobile quando o URL do cliente de desenvolvimento mudar - shells desatualizados causam falsos positivos de "módulo não encontrado".
- Versão: Incremente
expo-dev-client com atualizações do SDK.
-
Builds da loja e alterações nativas nunca são apenas OTA: Se um recurso JS requer um novo módulo nativo, envie primeiro um build da loja - restrinja o JS com verificações de versão em tempo de execução até que o limite de adoção seja atingido.
- Padrão: Política de versão em tempo de execução do
expo-updates + flag de recurso para nova API nativa.
- Veja: Regras de Lançamento e OTA.
-
Teste em dispositivos físicos para módulos de hardware: Câmera, BLE, NFC e push se comportam de maneira diferente em simuladores - QA apenas em simulador perde falhas de permissão e de segundo plano.
- Matriz: Documente a lista mínima de dispositivos por módulo nativo (por exemplo, Android 10 de gama média, iPhone SE).
- CI: Maestro em artefatos de prévia EAS, não no Expo Go.
-
Compatibilidade da Nova Arquitetura é explícita: RN 0.86 favorece a Nova Arquitetura - verifique se os módulos nativos de terceiros declaram suporte a Fabric/TurboModule ou documente o fallback.
- Verifique: README da biblioteca e avisos do
expo-doctor.
- ADR: Registre módulos que exigem a Arquitetura Antiga até que correções upstream sejam aplicadas.
-
Libere handles e listeners nativos: Instâncias de SharedObject de longa duração de módulos Expo (players, sensores) precisam de release() ao desmontar - vazamentos travam aplicativos em segundo plano.
- Padrão: A limpeza do
useEffect chama o remove() do módulo ou o remove() da assinatura.
- Perfil: Instrumentos do Xcode / Profiler do Android para vazamentos de módulos nativos antes do lançamento.
-
Módulos Expo personalizados vivem em modules/ com API JS tipada: Exporte uma superfície TypeScript estreita - recursos importam @/modules/my-feature, não strings NativeModules brutas.
- Testes: Mock na fronteira do módulo em Jest; E2E no dispositivo para integração.
- Docs: README na pasta do módulo com matriz de suporte de plataforma.
-
Sem lógica de negócios em código nativo: A camada nativa lida com APIs de plataforma e marshaling - regras de precificação e validação permanecem em TypeScript.
- Cheiro: Swift
if user.isPremium duplicado do JS.
- Correção: Passe primitivos através da ponte; mantenha uma única fonte de verdade em JS.
-
Versionamento semântico para módulos internos: Alterações de API nativa que quebram exigem um build da loja e um changelog - trate modules/ como um pacote publicado.
- Coordene: O descompasso de versão JS e nativo é impossível em um único bundle - envie juntos.
- Monorepo: Módulos internos ainda recebem entradas no CHANGELOG.
-
Revisão de segurança para módulos nativos que tocam em segredos: Wrappers de keychain, SDKs de pagamento e bibliotecas de atestado precisam de aprovação de segurança - não apenas revisão do líder mobile.
-
Prebuild no CI em PRs nativos: Execute npx expo prebuild --clean --no-install (ou build EAS completo) para capturar falhas de plugin antes do merge.
- Cache: Builds remotos EAS são aceitáveis quando o prebuild local é lento.
- Artefato: Anexe um resumo do diff do prebuild ao PR para o revisor.
-
ADR para cada módulo nativo personalizado e dependência nativa não-Expo: Status, proprietário, alternativas consideradas, posição da Nova Arquitetura e gatilho de aposentadoria.
- Tier 1 (1–6): Caminho de integração - escolher o tier errado custa semanas de manutenção nativa.
- Tier 2 (7–12): Instalação e plugins - corrige o prebuild antes que os desenvolvedores baixem clientes de desenvolvimento quebrados.
- Tier 3 (13–18): Fluxo de trabalho CNG - garante que os binários correspondam às expectativas do JavaScript.
- Tier 4 (19–24): Governança - evita o acúmulo de dívida nativa.
Módulo Expo vs módulo nativo do React Native?
Prefira a API de Módulos do Expo para novas pontes personalizadas - autolinking, TypeScript e plugins de configuração integram-se com CNG. Módulos nativos legados do RN funcionam, mas exigem mais manutenção de linking manual no SDK 57.
Quando a edição manual de ios/ é aceitável?
Aplicativos Brownfield com pastas nativas commitadas e uma estratégia de merge documentada. Aplicativos Expo greenfield padrão nunca devem editar manualmente arquivos gerados - use plugins de configuração.
Preciso reconstruir após adicionar um plugin de configuração?
Sim - plugins mutam projetos nativos no tempo de prebuild. Execute um novo cliente de desenvolvimento e build da loja; OTA sozinho é insuficiente.
Como sei se um pacote funciona com o Expo Go?
Verifique a documentação do Expo - se o pacote não estiver no bundle do Expo Go, você precisa de um build de desenvolvimento. expo-doctor também pode avisar sobre dependências incompatíveis.
Posso enviar um módulo nativo via OTA?
Não - o código nativo é enviado no binário. Você pode enviar JS que chama um módulo nativo existente via OTA, mas adicionar o módulo em si requer um build da loja.
Qual é o ponto de entrada da API de Módulos do Expo?
Crie um módulo com npx create-expo-module@latest, registre-o nos workspaces do package.json do aplicativo ou na pasta modules/, e o autolinking o captura no prebuild.
Como monorepos compartilham módulos nativos?
Coloque módulos compartilhados em packages/native-feature/ com dependências react-native adequadas. Um aplicativo executa o prebuild; o módulo se autovincula do caminho do workspace que o Metro resolve.
A Nova Arquitetura quebra módulos nativos mais antigos?
Alguns módulos da comunidade atrasam o suporte a Fabric/TurboModule no RN 0.86. Verifique antes de adotar; documente o fallback da Arquitetura Antiga em um ADR se for temporariamente necessário.
Quando devo fazer um fork de uma dependência nativa?
Quase nunca - envie uma correção upstream ou envolva com um plugin de configuração. Forks quando o mantenedor se foi exigem um ADR com propriedade de patch de segurança.
Como testar módulos nativos em Jest?
Faça mock na fronteira TypeScript (jest.mock('@/modules/my-feature')) com formas de retorno realistas. Execute testes de integração no dispositivo via Maestro ou QA manual para caminhos de hardware.
O que aciona `expo prebuild --clean`?
Atualizações do SDK, alterações de plugin, falhas de autolinking e erros de build nativo inexplicáveis. --clean é o caminho de recuperação padrão no SDK 57 - não é um último recurso.
Os plugins de configuração podem ser executados apenas no EAS Build?
Plugins são executados em qualquer prebuild - local e remoto. Mantenha o prebuild local reproduzível para que o CI e os laptops gerem projetos nativos idênticos.
Quem é responsável pela manutenção de módulos nativos?
O ADR nomeia um proprietário principal (iOS/Android ou full-stack mobile). Código nativo sem proprietário é um bloqueador de merge em equipes maduras.
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).