Configure como o Expo pré-compila projetos nativos, como seu aplicativo carrega no Expo Go e em builds de desenvolvimento, e quais valores não secretos chegam ao JavaScript em tempo de execução - sem vazar credenciais para o bundle.
# Inspecione o manifesto público resolvido (o que Constants.expoConfig exporá)APP_ENV=development EXPO_PUBLIC_API_URL=https://staging.api.acme.test npx expo config --type public
Quando usar isso:
Definir identificadores de bundle, ícones, splash screen, scheme de deep-link e configurações do EAS Update.
Ramificar o nome do aplicativo, URLs de API ou flags de recursos por ambiente sem manter três repositórios.
Passar valores não secretos de tempo de execução para JS via extra e Constants.expoConfig.
Registrar plugins de configuração que modificam android/ e ios/ durante o prebuild.
// src/config/runtime.ts - leia a configuração resolvida em tempo de execução (não app.config.ts bruto)import Constants from "expo-constants";type Extra = { appEnv: "development" | "staging" | "production"; apiUrl: string; featureFlags: { newCheckout: boolean };};const extra = Constants.expoConfig?.extra as Extra;export const appEnv = extra.appEnv;export const apiUrl = extra.apiUrl;export const featureFlags = extra.featureFlags;
# Desenvolvimento local (API de staging)APP_ENV=staging EXPO_PUBLIC_API_URL=https://staging.api.acme.test npx expo start# Build de produção EAS - segredos vivem no EAS, não em app.configAPP_ENV=production eas build --profile production --platform ios
O que isso demonstra:
app.config.ts mescla valores estáticos de app.json usando o padrão de middleware ({ config }).
APP_ENV alterna identificadores nativos e nome de exibição por ambiente.
Variáveis EXPO_PUBLIC_* são incorporadas ao JS no momento do bundle; extra expõe a configuração via Constants.expoConfig.
npx expo config --type public pré-visualiza o manifesto visível para o cliente antes do envio.
O Expo CLI procura por configuração estática (app.json ou app.config.json) e configuração dinâmica (app.config.js / app.config.ts). Se ambos existirem, o dinâmico prevalece após a mesclagem.
Se a configuração dinâmica exportar uma função, o Expo passa a configuração estática normalizada como { config } e usa o valor de retorno como o manifesto final.
A configuração resolvida é serializada para JSON antes que qualquer ferramenta (Metro, EAS, prebuild) a consuma - sem Promises, sem assincronismo.
Campos na configuração pública são incorporados aos builds e disponíveis via Constants.expoConfig. Chaves sensíveis (hooks, ios.config, android.config, campos de assinatura de atualização) são filtradas.
Plugins de configuração declarados em plugins são executados durante npx expo prebuild e EAS Build para mutar projetos nativos.
Se presente na raiz, apenas o objeto expo aninhado é usado
# Configuração completa resolvida (inclui campos apenas nativos)npx expo config# Subconjunto público - corresponde ao que o JS pode ler em tempo de execuçãonpx expo config --type public
Sim (apenas tempo de build, não incorporado automaticamente)
extra → Constants.expoConfig.extra
Variáveis de ambiente / segredos do EAS
Servidores EAS Build
Segredos sim (lado do servidor)
Injetado em extra no tempo de build
Campo extra
Gravado no manifesto
Não - enviado no binário
Constants.expoConfig.extra
// .env.development (commitado - sem segredos)EXPO_PUBLIC_API_URL=http://localhost:4000APP_ENV=development
// Código de recurso - EXPO_PUBLIC_ deve usar notação de ponto (necessário para inlining)const url = process.env.EXPO_PUBLIC_API_URL; // ✓// const url = process.env["EXPO_PUBLIC_API_URL"]; // ✗ não será inlined
Segredos em EXPO_PUBLIC_ ou extra - Ambos acabam no bundle do cliente; qualquer pessoa pode extraí-los. Correção: Mantenha segredos no seu servidor; use tokens de curta duração; armazene segredos de build apenas no EAS Secrets.
Desestruturação de process.env - const { EXPO_PUBLIC_X } = process.env não é inlined pelo Metro. Correção: Sempre use a notação de ponto process.env.EXPO_PUBLIC_X no código do aplicativo.
Importar app.config.ts de componentes - Traz lógica apenas do Node para o Metro e pode vazar o tratamento de ambiente em tempo de build. Correção: Leia Constants.expoConfig ou process.env.EXPO_PUBLIC_* apenas no código do aplicativo.
Esperar que app.config recarregue como Fast Refresh - A configuração é reavaliada quando o Metro reinicia, não a cada hot reload. Correção: Reinicie expo start após alterar app.config.ts; recarregue completamente o aplicativo para alterações em EXPO_PUBLIC_.
Mesmo ID de bundle entre staging e production - Instalar ambos os builds em um dispositivo sobrescreve o outro. Correção: Sufixe identificadores (com.acme.mobile.staging) por ambiente.
Promises na configuração dinâmica - export default async () => ({}) é inválido; a configuração deve retornar de forma síncrona. Correção: Leia variáveis de ambiente de forma síncrona; busque configuração remota da sua API em tempo de execução do aplicativo.
Confiar em NODE_ENV para escolher arquivos .env - expo export e eas update forçam NODE_ENV=production. Correção: Use APP_ENV explícito ou eas env:pull para alternância de ambiente.
Qual é a diferença entre app.json e app.config.js?
app.json é JSON estático que as ferramentas podem atualizar automaticamente. app.config.js / app.config.ts é dinâmico - suporta variáveis, ramificação de ambiente e TypeScript. O Expo mescla o estático no dinâmico quando você exporta uma função.
Qual arquivo deve conter minha configuração?
Mantenha um app.json mínimo se as ferramentas o esperarem, mas prefira app.config.ts como a fonte da verdade para qualquer coisa dependente do ambiente. Execute npx expo config para ver o resultado mesclado.
Como leio valores de configuração dentro do meu aplicativo React Native?
Use expo-constants:
import Constants from "expo-constants";const apiUrl = Constants.expoConfig?.extra?.apiUrl;
Para variáveis EXPO_PUBLIC_, use process.env.EXPO_PUBLIC_API_URL diretamente nos arquivos de origem.
Por que não devo importar app.json em componentes?
Importações diretas contornam o pipeline de processamento de configuração do Expo e podem empacotar o conteúdo bruto do arquivo. Constants.expoConfig retorna o manifesto resolvido e seguro para o público usado nos builds.
O que o npx expo config --type public mostra?
O subconjunto de configuração incorporado ao seu aplicativo e exposto ao JavaScript - a mesma forma disponível através de Constants.expoConfig. Use-o para auditar vazamentos antes do lançamento.
Como funcionam as variáveis de ambiente EXPO_PUBLIC_?
O Expo CLI carrega arquivos .env e incorpora referências process.env.EXPO_PUBLIC_* ao seu bundle JavaScript no momento do build. Eles são visíveis para os usuários finais - nunca armazene segredos lá.
Para que serve o campo extra?
extra é um objeto JSON arbitrário copiado para o manifesto público. Passe flags de recursos, rótulos de ambiente ou endpoints não sensíveis. Leia-o via Constants.expoConfig.extra.
Como configuro diferentes IDs de bundle por ambiente?
Defina APP_ENV ao executar eas build ou localmente no seu shell.
O app.config.ts pode usar async/await ou fetch?
Não. A configuração dinâmica deve retornar um objeto simples de forma síncrona - sem Promises. Busque configurações remotas da sua API após o lançamento do aplicativo em JavaScript.
Armadilha: Por que minha variável EXPO_PUBLIC_ apareceu como undefined?
Causas comuns: prefixo EXPO_PUBLIC_ ausente, uso de notação de colchetes (process.env['EXPO_PUBLIC_X']), ou esquecer de reiniciar o Metro após alterar .env. Corrija o prefixo, use notação de ponto e execute npx expo start --clear.
Como os plugins de configuração se relacionam com app.config?
Liste os nomes ou caminhos dos plugins no array plugins. Eles são executados durante o prebuild/EAS Build para modificar projetos nativos (permissões, entitlements, Gradle). Eles não são executados no Expo Go para código nativo que ainda não está empacotado lá.
Devo fazer commit dos arquivos .env?
Faça commit de .env com padrões não secretos, se útil. Nunca faça commit de .env.local ou arquivos com credenciais. Adicione .env*.local ao .gitignore.
Como APP_ENV difere de NODE_ENV?
NODE_ENV é controlado pelo Node e pelos bundlers - expo export força production. APP_ENV é uma variável personalizada que você controla para alternar entre staging/production em app.config.ts sem conflitar com as ferramentas.
Quais campos são filtrados da configuração pública?
hooks, ios.config, android.config e campos de assinatura de código do EAS Update são removidos de Constants.expoConfig. Não confie em lê-los do JS.
Como tipar expoConfig.extra em TypeScript?
Defina um tipo AppExtra compartilhado e faça o cast:
import Constants from "expo-constants";import type { AppExtra } from "../types/expo-extra";const extra = Constants.expoConfig?.extra as AppExtra;
Mantenha o tipo em um arquivo importado tanto por app.config.ts quanto pelo código de tempo de execução.