O que significa “build” e “distribuição” no React Native
Em React Native, “build” é o processo de transformar seu código JavaScript/TypeScript e configurações nativas em um artefato instalável: no Android, geralmente APK (instalação direta) ou AAB (publicação na Play Store); no iOS, um .ipa gerado a partir de um Archive no Xcode para distribuição via TestFlight/App Store ou instalação interna. “Distribuição” é o conjunto de passos para assinar, versionar, empacotar e entregar esse artefato para testes ou lojas.
Variantes de build: debug vs release (e flavors quando necessário)
Debug
- Focado em desenvolvimento: logs, ferramentas de depuração, e geralmente usa servidor Metro.
- No Android, é assinado automaticamente com uma chave de debug do sistema.
- No iOS, costuma rodar via Xcode em modo Debug com assinatura de desenvolvimento.
Release
- Focado em distribuição: otimizações, minificação (quando aplicável), sem ferramentas de debug.
- Exige assinatura com credenciais de produção (Android keystore / iOS certificados e provisioning).
- Gera artefatos para loja ou distribuição interna.
Flavors (Android) e Schemes/Configurations (iOS)
Se você precisa de múltiplos ambientes (ex.: dev, staging, prod) com IDs, ícones ou endpoints diferentes, no Android isso é feito com productFlavors e no iOS com Schemes e Build Configurations. Mesmo sem flavors, entender a separação debug/release já cobre a maior parte dos casos.
Android: assinatura, versionamento e geração de APK/AAB
1) Ajuste de versionCode e versionName
No Android, o versionamento é controlado principalmente em android/app/build.gradle (ou android/app/build.gradle.kts em Kotlin DSL). Dois campos são críticos:
versionName: versão “humana” (ex.:1.4.0).versionCode: inteiro incremental obrigatório para a Play Store (ex.:10400).
Exemplo (Groovy):
android { defaultConfig { applicationId "com.suaempresa.seuapp" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 10400 versionName "1.4.0" }}Boas práticas para versionCode:
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
- Sempre incrementar a cada upload na Play Store.
- Adotar uma regra previsível (ex.:
major*10000 + minor*100 + patch).
2) Criando um keystore (chave de assinatura)
Para assinar builds de release, crie um keystore e guarde-o com segurança. Exemplo com keytool:
keytool -genkeypair -v -storetype JKS -keystore seuapp-release.keystore -alias seuapp -keyalg RSA -keysize 2048 -validity 10000Recomendações:
- Faça backup do arquivo
.keystoree das senhas (store password e key password). - Não comite o keystore no repositório.
- Use variáveis de ambiente/arquivos locais ignorados pelo Git para senhas.
3) Configurando assinatura no Gradle
Crie/edite android/gradle.properties (ou use variáveis de ambiente no CI). Exemplo (não comitar se contiver segredos):
MYAPP_UPLOAD_STORE_FILE=seuapp-release.keystore MYAPP_UPLOAD_KEY_ALIAS=seuapp MYAPP_UPLOAD_STORE_PASSWORD=******** MYAPP_UPLOAD_KEY_PASSWORD=********Em android/app/build.gradle:
android { signingConfigs { release { if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) { storeFile file(MYAPP_UPLOAD_STORE_FILE) storePassword MYAPP_UPLOAD_STORE_PASSWORD keyAlias MYAPP_UPLOAD_KEY_ALIAS keyPassword MYAPP_UPLOAD_KEY_PASSWORD } } } buildTypes { debug { // debug usa assinatura padrão signingConfig signingConfigs.debug } release { signingConfig signingConfigs.release minifyEnabled false shrinkResources false // Proguard/R8 pode ser habilitado conforme necessidade // proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }}Observação: para Play Store, é comum usar “Upload Key” e habilitar “Play App Signing”. Assim, você assina o upload e a Play Store re-assina para distribuição.
4) Gerando AAB (Play Store) e APK (instalação direta)
Com o ambiente Android configurado, execute na pasta android:
- Gerar AAB (recomendado para Play Store):
./gradlew bundleReleaseO arquivo costuma sair em:
android/app/build/outputs/bundle/release/app-release.aab- Gerar APK de release (útil para distribuição interna/QA):
./gradlew assembleReleaseO arquivo costuma sair em:
android/app/build/outputs/apk/release/app-release.apk5) Validando o artefato Android antes de publicar
- Instale o APK em um dispositivo real e verifique fluxo crítico (login, navegação principal, permissões).
- Confirme se o build está em release (sem menu de dev, sem logs excessivos).
- Verifique se o
versionCodeé maior que o último publicado. - Teste em diferentes versões do Android e densidades de tela (ícone/splash).
iOS: certificados, provisioning, versionamento e Archive
1) Version (CFBundleShortVersionString) e Build (CFBundleVersion)
No iOS, há dois valores principais:
- Version (ex.:
1.4.0) — equivalente aoversionName. - Build (ex.:
57) — número incremental; deve aumentar a cada envio ao TestFlight/App Store.
Você ajusta isso no Xcode em Target > General (ou em Info.plist dependendo da configuração). Em termos de chaves:
CFBundleShortVersionString= VersionCFBundleVersion= Build
2) Certificados e Provisioning Profiles (visão prática)
Para distribuir um app iOS, você precisa alinhar três elementos:
- Bundle Identifier (ex.:
com.suaempresa.seuapp). - Certificado (Development ou Distribution).
- Provisioning Profile que vincula o Bundle ID ao certificado e (no caso de desenvolvimento/ad hoc) aos dispositivos.
Fluxo comum:
- Para testes internos: TestFlight (recomendado) usando perfil de distribuição App Store.
- Para instalação direta em dispositivos específicos: Ad Hoc (exige listar UDIDs).
3) Assinatura no Xcode (Automatic vs Manual)
No Xcode, em Signing & Capabilities:
- Automatic Signing: o Xcode gerencia perfis automaticamente (bom para times pequenos e fluxo simples).
- Manual Signing: você seleciona o provisioning profile e certificado (útil em cenários corporativos/CI mais controlado).
Checklist rápido:
- O
Bundle Identifierdo target corresponde ao registrado no Apple Developer. - O time (Team) correto está selecionado.
- Não há conflitos de capabilities (ex.: Push Notifications, Associated Domains) sem configuração no portal.
4) Gerando Archive e distribuindo (TestFlight/App Store)
Passo a passo no Xcode:
- Selecione o esquema do app e um destino genérico (ex.: Any iOS Device (arm64)).
- Menu Product > Archive.
- Ao finalizar, abra o Organizer e selecione o Archive gerado.
- Clique em Distribute App e escolha:
- App Store Connect para TestFlight/App Store.
- Ad Hoc para distribuição em dispositivos listados.
- Development para builds de desenvolvimento.
Validações importantes no upload:
- O Build Number precisa ser maior que o último enviado para a mesma Version.
- Ícones e splash devem estar presentes e sem transparência indevida (especialmente ícone iOS).
- Permissões e descrições no
Info.plistdevem existir para recursos usados (câmera, localização etc.).
Ícones e Splash: estratégia de assets e geração
Conceitos: App Icon vs Splash Screen
- App Icon: ícone exibido na home, app switcher e loja. Precisa de múltiplos tamanhos e regras específicas por plataforma.
- Splash Screen: tela inicial enquanto o app carrega. No iOS e Android modernos, é recomendado usar uma abordagem nativa simples (fundo + logo central) para evitar “piscar” e inconsistências.
Organização recomendada de arquivos
- Mantenha fontes em alta resolução em uma pasta de design, por exemplo:
assets/branding/icon.pngeassets/branding/splash.png. - Evite editar manualmente dezenas de tamanhos; prefira geração automatizada.
Geração automática com biblioteca (exemplo prático)
Uma abordagem comum é usar uma biblioteca que gere ícones e splash a partir de um arquivo fonte. Um exemplo popular é react-native-bootsplash para splash (e pode ser combinado com geradores de ícone). Fluxo típico:
- Adicionar a dependência e seguir o guia da biblioteca para integrar no Android e iOS.
- Gerar assets a partir de uma imagem fonte e uma cor de fundo.
Exemplo de comando (varia conforme a ferramenta escolhida):
npx react-native-bootsplash generate --platforms=android,ios --background=FFFFFF --logo=assets/branding/splash-logo.pngPara ícones, você pode usar geradores específicos (CLI) que criam os tamanhos e colocam nos diretórios corretos. O ponto-chave é: defina um único arquivo fonte (quadrado, alta resolução) e gere os tamanhos automaticamente para evitar inconsistência.
Regras práticas para ícones
- Use PNG quadrado em alta resolução (ex.: 1024x1024) como fonte.
- Evite bordas “coladas”; deixe margem de respiro para diferentes máscaras.
- No iOS, evite transparência no ícone final (pode causar rejeição/alertas).
- No Android, considere ícone adaptativo (foreground/background) quando aplicável.
Regras práticas para splash
- Prefira fundo sólido e logo central, sem textos.
- Garanta contraste suficiente e teste em telas pequenas e grandes.
- Evite imagens enormes como splash completo; isso aumenta tempo de carregamento e pode distorcer.
Permissões e configurações: AndroidManifest e Info.plist
Android: AndroidManifest.xml
Permissões devem refletir exatamente o que o app usa. Exemplos comuns:
<manifest ...> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <application ...> ... </application></manifest>Pontos de atenção:
- Algumas permissões exigem declarações adicionais (ex.: recursos de localização em background, notificações, etc.).
- Remova permissões não utilizadas para reduzir fricção em revisão e aumentar confiança do usuário.
- Verifique
android:exportedem componentes quando exigido por versões recentes do Android (especialmente se houver intent-filters).
iOS: Info.plist
No iOS, além de permissões, você precisa fornecer descrições (strings) exibidas ao usuário. Exemplos:
<key>NSCameraUsageDescription</key> <string>Precisamos da câmera para ...</string> <key>NSLocationWhenInUseUsageDescription</key> <string>Usamos sua localização para ...</string> <key>NSPhotoLibraryUsageDescription</key> <string>Precisamos acessar suas fotos para ...</string>Pontos de atenção:
- Se o app acessa um recurso e a chave não existe, o app pode crashar ao solicitar a permissão.
- As descrições devem ser claras e específicas (evite textos genéricos).
Checklist de validação antes de publicar
Checklist geral (Android e iOS)
- Versão e build incrementados (
versionCode/versionName, Version/Build). - Build em modo release (sem dev menu, sem endpoints de teste, sem chaves de debug).
- Ícone e splash revisados em dispositivos reais.
- Permissões mínimas necessárias e descrições corretas.
- Testes de fluxo crítico: login, onboarding, navegação principal, logout, modo offline (se aplicável).
- Validação de API keys/segredos: não expor chaves sensíveis no app (quando aplicável, use backend/proxy).
Checklist Android específico
- AAB gerado e assinado corretamente.
- Verificar
minSdkVersion/targetSdkVersionconforme exigências atuais. - Conferir se o
applicationIdestá correto (e não é o de staging).
Checklist iOS específico
- Archive gerado com assinatura de distribuição.
- Bundle Identifier correto e capabilities configuradas.
- Build number incrementado para cada upload ao TestFlight.
Troubleshooting prático de builds (erros comuns e como atacar)
1) “Funciona no debug, quebra no release”
- Confirme se o app não depende de logs/flags de debug.
- Verifique se endpoints e variáveis de ambiente estão corretos para release.
- No Android, se habilitar minificação (R8/Proguard), pode ser necessário adicionar regras em
proguard-rules.propara bibliotecas específicas.
2) Erros de assinatura no Android
- Keystore não encontrado: confira caminho do arquivo e se está acessível no ambiente atual.
- Senha/alias inválidos: valide
storePassword,keyPasswordekeyAlias. - Upload rejeitado na Play Store: confirme se o
versionCodeaumentou e se você está usando a chave de upload correta (Play App Signing).
3) Erros de certificados/provisioning no iOS
- No matching provisioning profiles found: o Bundle ID não bate com o profile, ou o profile não inclui o certificado atual.
- Team/Signing mismatch: selecione o Team correto e re-gere perfis se necessário.
- Capabilities faltando: habilite a capability no portal e no Xcode (ex.: Push, Sign in with Apple).
4) Build falha por cache/estado do projeto
Quando alterações de dependências ou configurações nativas geram erros estranhos, um reset de caches costuma ajudar. Exemplos de ações comuns:
- Android: limpar build do Gradle:
cd android && ./gradlew clean- iOS: limpar build no Xcode (Product > Clean Build Folder) e, se aplicável, reinstalar pods.
- Reinstalar dependências JS e reconstruir (quando houver inconsistência).
5) Problemas com ícones/splash não atualizando
- Confirme que os assets foram gerados nos diretórios corretos (mipmap/drawable no Android, Assets.xcassets no iOS).
- Limpe build e reinstale o app no dispositivo (ícones podem ficar cacheados).
- Verifique se o nome do asset e referências nativas estão corretos.
Organizando um pipeline manual de release (passo a passo repetível)
1) Preparação de versão
- Defina a versão (ex.:
1.4.0) e incremente: - Android:
versionNameeversionCode. - iOS: Version e Build.
- Android:
- Garanta que ícones/splash estão finalizados e aplicados.
2) Build Android
- Atualize credenciais de assinatura (se necessário) e confirme que o keystore está disponível.
- Gere
AABpara Play Store:
cd android && ./gradlew bundleRelease- Instale e teste um APK de release (opcional, mas recomendado para QA interno):
cd android && ./gradlew assembleRelease3) Build iOS
- Abra o projeto no Xcode, selecione o esquema correto.
- Confirme assinatura e Team.
- Atualize Version/Build.
- Gere Archive e distribua via App Store Connect (TestFlight).
4) Validação final
- Teste o build distribuído (APK interno/TestFlight) em pelo menos 1 dispositivo por “família” (Android e iOS) e, idealmente, em versões diferentes.
- Revise permissões solicitadas e textos de uso no iOS.
- Confirme que o app abre sem depender do Metro e sem telas de erro.
5) Registro e rastreabilidade
- Mantenha um registro simples por release: versão, build, data, hash do commit, e observações de mudanças de configuração nativa (ícone/splash/permissões).
- Se usar múltiplos ambientes, registre qual flavor/scheme foi distribuído.