Guia completo
Expo: guia completo do projeto à publicação nas lojas
Aprenda Expo Router, development builds, configuração, recursos nativos, EAS Build, Update e Submit levando um app React Native até as lojas.
Expo organiza o caminho inteiro de um aplicativo React Native: criar o projeto, abrir no aparelho, navegar entre telas, instalar módulos compatíveis, configurar Android e iOS, gerar builds assinados, distribuir versões de teste e enviar às lojas. Ele não substitui React Native; fornece uma estrada pavimentada em volta dele.
Neste guia, a gente vai preparar o aplicativo de hábitos Passo a Passo para sair do QR code de desenvolvimento e chegar a uma versão instalável. Você vai saber quando Expo Go basta, quando criar development build, o que o prebuild realmente faz e onde terminam EAS Build, Update e Submit.
Se componentes, estado, lista e APIs ainda forem novidade, comece pelo
guia de React Native. Aqui o foco não é ensinar de
novo View e useState; é dominar o ciclo de vida do projeto que carrega esses
componentes.
Uma central de produção para duas plataformas
Imagine uma cozinha que entrega o mesmo cardápio em dois bairros. A receita é a mesma, mas cada unidade tem fornecedores, licenças, equipamentos e endereço próprios. React Native descreve boa parte do prato. Expo ajuda a coordenar as dependências, configurações, credenciais e entregas de Android e iOS.
O nome técnico é framework: um conjunto de ferramentas e convenções que
decide parte da estrutura para reduzir trabalho repetitivo. create-expo-app
monta o projeto; Expo Router organiza navegação; módulos Expo acessam recursos;
EAS pode construir, atualizar e enviar artefatos.
A comparação tem limite. Expo não transforma duas plataformas em uma só. Android e iOS ainda têm permissões, certificados, convenções e revisão diferentes. O framework automatiza tarefas e oferece uma interface comum, mas a equipe precisa testar cada destino.
As quatro coisas chamadas “Expo”
Separar os nomes evita muita conversa atravessada:
- Expo SDK é o conjunto de pacotes e APIs versionados para projetos React Native.
- Expo Go é um aplicativo genérico para experimentar projetos compatíveis sem compilar seu próprio binário.
- Development build é o seu aplicativo nativo preparado para desenvolvimento, com os módulos escolhidos pelo projeto.
- EAS, Expo Application Services, é o conjunto de serviços e comandos para build, credenciais, updates e envio.
Quando alguém diz “funciona no Expo”, pergunte em qual desses contextos. Um módulo pode funcionar num development build e não estar incluído no Expo Go. Um código pode abrir localmente e ainda falhar no build de produção por configuração ou credencial.
Criando o projeto com uma versão coerente
Use o gerador oficial:
npx create-expo-app@latest passo-a-passo
cd passo-a-passo
npm start@latest escolhe a versão atual do gerador. O projeto criado fixa dependências
compatíveis no package.json; não significa que todo pacote instalado depois
deve usar sua versão mais nova indiscriminadamente.
Ao adicionar biblioteca integrada ao SDK, prefira:
npx expo install expo-cameraexpo install consulta a matriz do projeto e escolhe uma versão compatível.
Compare com uma tomada: não basta comprar o modelo lançado ontem; plugue e tensão
precisam combinar com a casa.
Cheque a saúde:
npx expo-doctor
npx expo install --checkSe o segundo comando encontrar divergência, leia antes de aceitar atualização em massa. Lockfile deve entrar no Git. Ele registra o conjunto exato que a equipe e a esteira vão instalar.
Uma estrutura inicial com Router pode parecer assim:
passo-a-passo/
app/
_layout.tsx
index.tsx
habits/
[id].tsx
assets/
components/
lib/
app.json
eas.json
package.jsonMantenha arquivos de rota focados em montar telas. Componentes reutilizáveis,
acesso à API, validação e armazenamento não precisam morar todos dentro de
app/. Rota é endereço, não pasta universal do produto.
Expo Go, emulador e aparelho real
Expo Go oferece o ciclo mais curto: abre o cliente, lê o QR code e carrega o bundle. Ele é ideal para aprender componente, estilo e estado. O limite é seu binário pré-construído: se o módulo nativo não está nele, JavaScript nenhum pode adicioná-lo em tempo de execução.
Um emulador Android ou simulador iOS facilita repetir estados e controlar versão. O aparelho real mostra o que eles escondem: câmera verdadeira, rede móvel, memória, aquecimento, gesto, teclado, fonte do usuário e notificação.
Use os três com propósitos diferentes:
Expo Go -> conceito e protótipo compatível
simulador -> ciclo rápido e cenários reproduzíveis
aparelho real -> hardware, desempenho e experiênciaNão espere a semana de publicação para tocar num aparelho. Uma interface que parece precisa com mouse pode ter alvos pequenos, teclado cobrindo botão e texto cortado quando a fonte está ampliada.
Development build é a sua oficina móvel
Quando o projeto usa código nativo próprio, notificações configuradas, mapas ou outro módulo fora do Expo Go, instale o cliente de desenvolvimento:
npx expo install expo-dev-clientDepois gere um development build localmente ou pelo EAS. Esse binário é uma versão da sua aplicação com ferramentas de desenvolvimento. Ele conhece os módulos nativos do projeto e recebe bundles do servidor Metro.
Pense em Expo Go como uma cozinha compartilhada com utensílios predefinidos. Development build é sua própria cozinha de teste: você escolhe os utensílios e precisa reconstruí-la quando instala um equipamento fixo novo. Alterar apenas JavaScript não exige outro binário; alterar a parte nativa geralmente exige.
Uma equipe deve tornar o build reproduzível e distribuí-lo aos testadores. Se cada pessoa modifica Android ou iOS manualmente sem registrar o motivo, a fonte da verdade se perde.
Expo Router: arquivo vira rota, layout vira moldura
Expo Router usa rotas baseadas em arquivos. app/index.tsx representa a raiz;
app/habits/[id].tsx recebe um segmento dinâmico; _layout.tsx configura o
navegador que envolve um grupo.
import { Stack } from 'expo-router';
export default function RootLayout() {
return (
<Stack>
<Stack.Screen name="index" options={{ title: 'Hábitos' }} />
<Stack.Screen name="habits/[id]" options={{ title: 'Detalhe' }} />
</Stack>
);
}Navegue com endereço, não com importação manual de tela:
import { router } from 'expo-router';
router.push({ pathname: '/habits/[id]', params: { id: 'agua' } });Na tela de destino:
import { useLocalSearchParams } from 'expo-router';
const { id } = useLocalSearchParams<{ id: string }>();Parâmetro de URL é entrada não confiável. Mesmo com o tipo, valide presença, formato e existência do hábito. TypeScript ajuda o editor, mas uma deep link externa não leu seu tipo.
Layouts aninhados permitem separar pilha de autenticação, tabs e modal. Comece com duas rotas; desenhar cinco navegadores antes da primeira tela cria complexidade sem comportamento para testar.
app.json e app.config: a identidade do binário
O arquivo de configuração define nome, slug, esquema de link, ícone, orientação e propriedades específicas das plataformas:
{
"expo": {
"name": "Passo a Passo",
"slug": "passo-a-passo",
"scheme": "passoapasso",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"android": {
"package": "br.com.devclub.passoapasso"
},
"ios": {
"bundleIdentifier": "br.com.devclub.passoapasso"
}
}
}android.package e ios.bundleIdentifier são documentos de identidade. Depois
de publicar, mudar esses valores cria outro aplicativo para a loja. Escolha com
domínio controlado e confirme antes do primeiro envio.
Quando a configuração depende de ambiente, app.config.ts permite código:
import type { ExpoConfig, ConfigContext } from 'expo/config';
export default ({ config }: ConfigContext): ExpoConfig => ({
...config,
name: process.env.APP_VARIANT === 'production'
? 'Passo a Passo'
: 'Passo a Passo Dev',
extra: {
apiUrl: process.env.EXPO_PUBLIC_API_URL,
},
});Configuração dinâmica deve continuar previsível. Execute npx expo config em
cada ambiente e revise o resultado resolvido. Não coloque segredo em extra ou
variável EXPO_PUBLIC_*: o valor vai para um aplicativo distribuído a terceiros.
Ícone, splash e assets têm especificação, não improviso
Lojas e sistemas cortam ícones em formatos diferentes. Use arquivo quadrado de alta resolução, preserve área segura e teste fundo claro e escuro. Android pode usar adaptive icon com foreground e background separados; iOS aplica sua própria máscara.
Splash screen existe durante a preparação do aplicativo. Ela não deve fingir que carregamento terminou nem esconder uma inicialização longa. Mantenha marca simples, faça o app decidir o estado inicial rapidamente e mostre interface de carregamento quando houver trabalho real.
Assets entram no bundle ou são baixados. Imagem enorme exibida como miniatura continua enorme na memória e na rede. Exporte tamanhos adequados, escolha formato e declare dimensões quando possível.
Crie uma verificação visual: instalação limpa em Android e iOS, toque no ícone, observe splash, primeira tela e retorno do background. O critério não é “a arte existe na pasta”; é transição sem flash, corte ou tela vazia.
Permissões e config plugins
Câmera, foto, localização e notificação precisam de configuração nativa e permissão em tempo de execução. Bibliotecas Expo usam config plugins para aplicar mudanças nos projetos nativos durante prebuild.
No código, peça permissão somente quando o recurso fizer sentido:
import { CameraView, useCameraPermissions } from 'expo-camera';
const [permission, requestPermission] = useCameraPermissions();
if (!permission) return <Loading />;
if (!permission.granted) {
return <PermissionExplanation onContinue={requestPermission} />;
}
return <CameraView style={{ flex: 1 }} />;A tela explica por que o Passo a Passo quer câmera antes de abrir o diálogo do sistema. Se a pessoa negar, ofereça digitação ou seleção de arquivo quando o produto permitir. Permissão não é onboarding obrigatório para um recurso que ela talvez nunca use.
Depois de instalar ou configurar plugin nativo, recrie o development build. Um reload atualiza JavaScript, não permissões declaradas no manifesto nem código compilado.
Prebuild: gerar projeto nativo a partir da configuração
npx expo prebuild gera as pastas android e ios usando a configuração e os
plugins. O processo é parecido com compilar uma planta em documentos de obra.
A fonte principal deveria continuar na configuração e nos plugins, não em uma
sequência secreta de cliques no Xcode.
npx expo prebuild --clean--clean recria as pastas e pode descartar mudanças manuais. Use apenas quando
o projeto segue o fluxo em que essas pastas são geradas ou quando você já
preservou alterações nativas em plugin/controle de versão. Não execute como
ritual de debug sem saber onde vive a fonte da verdade.
Projetos que mantêm customização manual podem versionar android e ios. A
escolha muda a operação da equipe. O importante é documentar se as pastas são
artefato regenerável ou código mantido; tratá-las como os dois ao mesmo tempo
produz surpresa.
Perfis do EAS Build: desenvolvimento, teste e produção
Instale e autentique a CLI:
npm install --global eas-cli
eas login
eas build:configureO eas.json descreve perfis:
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal"
},
"production": {
"autoIncrement": true
}
}
}Development inclui ferramentas e conecta ao bundler. Preview é um artefato para teste interno próximo de produção. Production é a versão preparada para loja. Não entregue development build a cliente final: comportamento, menus e segurança não são os mesmos.
Gere por plataforma e perfil:
eas build --platform android --profile preview
eas build --platform ios --profile productionBuild em nuvem lê o repositório enviado, instala dependências, aplica configuração e assina. Um sucesso local não garante sucesso remoto se arquivo necessário está ignorado, variável existe só no seu terminal ou lockfile não foi salvo.
Credenciais: chave de assinatura é identidade
Android usa keystore; iOS usa certificados e provisioning profiles. EAS pode ajudar a gerar e armazenar credenciais, mas isso não reduz sua importância. Perder acesso à assinatura pode impedir atualização de um aplicativo já publicado.
Defina quem controla as contas, ative múltiplos fatores, registre acesso e tenha um procedimento de recuperação. Credencial não entra no Git nem em mensagem de chat. Pessoas saem da equipe; o aplicativo precisa continuar atualizável.
No primeiro build, a CLI pode fazer perguntas. Leia o alvo e a conta antes de confirmar. Automatização vem depois que o processo manual foi entendido e documentado.
EAS Update: mudar o compatível, não trocar o motor andando
EAS Update distribui bundle JavaScript e assets para binários compatíveis. Pense numa revista que recebe páginas novas dentro de uma capa já impressa. Você pode alterar conteúdo compatível; não pode adicionar câmera nativa a uma capa que foi impressa sem esse recurso.
A compatibilidade é governada pelo runtime. Binário e update precisam concordar sobre os módulos nativos disponíveis. Mudar SDK, plugin, permissão ou código nativo exige novo build e uma política de runtime que impeça update incompatível.
Use canais para separar preview e produção. Publique primeiro para equipe, execute a lista de fumaça e só então promova. Tenha rollback e monitore erro após lançamento. Atualização rápida aumenta a responsabilidade: você consegue entregar um defeito rápido também.
Respeite as regras das lojas. Update não é caminho para transformar o propósito do aplicativo ou fugir de revisão.
Submit entrega o pacote; a loja decide a publicação
Depois de um build de produção:
eas submit --platform android
eas submit --platform iosO envio coloca o artefato no console da loja. Ainda faltam metadados, faixa etária, política de privacidade, declaração de dados, screenshots, preço, territórios, testadores e revisão. Automatize o transporte sem confundir com aprovação.
Prepare a ficha enquanto desenvolve. Se o app coleta localização ou cria conta, a política e a experiência de exclusão não podem nascer na véspera. Teste conta de revisão, back-end acessível e instruções para recursos protegidos.
Faça rollout gradual quando disponível. Uma porcentagem pequena revela falhas em aparelhos que sua equipe não possui. Monitore crash, login, versão da API e feedback antes de ampliar.
Ambientes e automação: o build precisa saber para onde aponta
Desenvolvimento, preview e produção não são apenas nomes do EAS. Cada ambiente tem API, conta de analytics, deep link e política de log próprios. O erro mais perigoso não é o build falhar; é o build de produção funcionar apontando para o banco de homologação.
Faça a configuração produzir uma identidade visível. Uma versão de desenvolvimento pode acrescentar “Dev” ao nome e usar ícone diferente, enquanto o identificador também recebe sufixo. Assim duas versões convivem no aparelho e ninguém testa sem perceber no aplicativo público.
const variant = process.env.APP_VARIANT ?? 'development';
const production = variant === 'production';
export default {
expo: {
name: production ? 'Passo a Passo' : `Passo a Passo (${variant})`,
android: {
package: production
? 'br.com.devclub.passoapasso'
: `br.com.devclub.passoapasso.${variant}`,
},
ios: {
bundleIdentifier: production
? 'br.com.devclub.passoapasso'
: `br.com.devclub.passoapasso.${variant}`,
},
},
};O mecanismo se parece com variáveis de ambiente no Node, mas existe uma fronteira: valores usados no aplicativo podem terminar no bundle. Segredo consumido apenas pela etapa de build pode ficar protegido no serviço de CI; valor que o JavaScript precisa em runtime é inspecionável no aparelho.
Mapeie o perfil para o ambiente explicitamente:
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"env": { "APP_VARIANT": "development" }
},
"preview": {
"distribution": "internal",
"env": { "APP_VARIANT": "preview" }
},
"production": {
"autoIncrement": true,
"env": { "APP_VARIANT": "production" }
}
}
}Não copie token sensível para esse trecho versionado. Use a gestão de ambiente e segredos oferecida pela plataforma, limite quem altera valores e registre a mudança.
Na integração contínua, separe verificação de entrega. Todo pull request
pode instalar pelo lockfile, verificar tipos, rodar testes, executar
expo-doctor e resolver a configuração. Builds de preview podem acontecer em
branch aprovada; produção exige tag ou promoção deliberada.
npm ci
npx tsc --noEmit
npm test -- --runInBand
npx expo-doctor
APP_VARIANT=production npx expo config --type publicO último comando permite revisar o que o binário público receberá sem gerar um build caro. Procure identificador, versão, URL e plugin inesperado. Depois do build, um teste de fumaça instala o artefato, abre a primeira tela, autentica numa conta própria de teste e confirma a versão da API.
Pense na automação como uma catraca, não como um robô que publica tudo que passa. Ela verifica critérios repetíveis e registra qual commit gerou qual artefato. Aprovar produção continua sendo uma decisão explícita, com rollback e responsável identificados.
O exercício desta seção é criar os três perfis, imprimir a configuração resolvida e montar uma tabela com nome, package/bundle id, API e canal de update. Se duas linhas compartilharem algo que deveria estar isolado, corrija antes do primeiro usuário real.
Registre ainda a versão mínima do sistema operacional e a política de suporte. Um módulo novo pode elevar essa versão sem aparecer na interface. O build passa, mas parte da base deixa de atualizar. Compare o artefato com a versão publicada, meça quantos usuários seriam afetados e trate a mudança como decisão de produto, não como detalhe escondido de dependência.
Diagnóstico por camada
Quando o build falha, identifique onde:
expo-doctorencontra dependência ou configuração?- Metro consegue gerar o bundle?
- prebuild aplica plugins sem conflito?
- Gradle ou Xcode compila a parte nativa?
- assinatura encontra credencial correta?
- aplicativo inicia e conversa com a API do ambiente certo?
- a loja rejeitou binário ou metadado?
Guarde o primeiro erro útil, não apenas a última cascata. Compare o build que funcionou com o que falhou: lockfile, versão de Node, SDK, variável, perfil, credencial e commit.
Apagar node_modules, cache e projetos nativos pode ser uma hipótese controlada,
mas também destrói evidência. Rode comandos de diagnóstico, mude uma peça e
registre o resultado.
O caminho até uma entrega que outra pessoa instala
Siga a trilha de React Native e use Expo nesta ordem:
- crie o projeto e rode no aparelho;
- entenda Expo Go e seus limites;
- organize rotas e layouts;
- configure identidade, ambiente e assets;
- instale um módulo e crie development build;
- trate permissão negada e dispositivo real;
- configure perfis development, preview e production;
- gere artefatos assinados e distribua preview;
- prepare metadados, privacidade e envio;
- publique com rollout, observação e plano de retorno.
O tutorial App mobile com React Native, Expo e TypeScript aplica esse caminho num rastreador de hábitos com Expo Router, armazenamento local, integração HTTP e testes executáveis antes da etapa de loja.
A missão deste guia é produzir um preview do Passo a Passo. Ele deve ter identificador próprio, ícone, duas rotas, URL de API de homologação e uma câmera opcional com alternativa quando a permissão for negada. Outra pessoa precisa instalar sem conectar ao seu Metro.
Depois documente commit, perfil, versão, plataforma, URL do artefato e cinco testes executados. Se você consegue reproduzir o build, explicar qual parte pode receber update e apontar quem controla a assinatura, o projeto deixou de ser um QR code no seu notebook e virou produto entregável.
Trilha
React Native
O mesmo JavaScript rodando no celular, do primeiro componente à publicação nas lojas.
Perguntas frequentes
Expo Go e development build são a mesma coisa?
Usar Expo impede código nativo personalizado?
EAS Build publica o aplicativo automaticamente?
Posso atualizar o aplicativo sem passar pela loja?
Variável EXPO_PUBLIC é segura para guardar uma chave?
Preciso pagar para começar com Expo?
Fontes consultadas
- Expo Docs — Create a project — docs.expo.dev
- Expo Docs — Development builds — docs.expo.dev
- Expo Router — Introduction — docs.expo.dev
- Expo Docs — App configuration — docs.expo.dev
- Expo Docs — EAS Build — docs.expo.dev
- Expo Docs — EAS Update — docs.expo.dev
- Expo Docs — EAS Submit — docs.expo.dev