expo-dev-client transforma seu binário de depuração em um ambiente de desenvolvimento completo: um launcher para alternar servidores Metro, um menu dev extensível e suporte para todos os módulos nativos que seu projeto instala - o caminho padrão além do Expo Go no SDK 57.
Cartão de receita de referência rápida - pronto para copiar e colar.
# Adiciona a biblioteca (fixa a versão compatível para SDK 57)npx expo install expo-dev-client# Compila e instala um cliente de desenvolvimentonpx expo run:ios # simulador local / dispositivo USBnpx expo run:android --device# - ou nuvem -eas build --profile development --platform all# Serve JavaScript para o cliente de desenvolvimento (não para Expo Go)npx expo start --dev-client
// App.tsx - itens personalizados do menu dev + banner em tempo de execuçãoimport { useEffect } from "react";import { Button, Platform, StyleSheet, Text, View } from "react-native";import * as DevClient from "expo-dev-client";import * as Expo from "expo";async function registerDevTools() { if (!__DEV__) return; await DevClient.registerDevMenuItems([ { name: "Logar configuração do app", callback: () => { console.log("Executando no Expo Go?", Expo.isRunningInExpoGo()); }, shouldCollapse: true, }, { name: "Lançar erro de teste", callback: () => { throw new Error("Crash intencional do menu dev para QA"); }, shouldCollapse: true, }, ]);}export default function App() { useEffect(() => { registerDevTools().catch(console.error); }, []); return ( <View style={styles.container}> <Text style={styles.title}>Demo do expo-dev-client</Text> <Text style={styles.row}>Plataforma: {Platform.OS}</Text> <Text style={styles.row}> Executando no Expo Go: {Expo.isRunningInExpoGo() ? "sim" : "não"} </Text> <Text style={styles.hint}> Agite o dispositivo (ou pressione m no terminal) → abra o menu dev → experimente os itens personalizados. </Text> <Button title="Abrir menu dev" onPress={() => DevClient.openMenu()} /> </View> );}const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, title: { fontSize: 22, fontWeight: "700", marginBottom: 12 }, row: { fontSize: 14, color: "#475569", marginBottom: 4 }, hint: { marginTop: 16, fontSize: 12, color: "#64748b", textAlign: "center" },});
// eas.json - perfil de desenvolvimento com cliente dev habilitado{ "cli": { "version": ">= 16.0.0" }, "build": { "development": { "developmentClient": true, "distribution": "internal", "ios": { "simulator": true }, "android": { "gradleCommand": ":app:assembleDebug" } } }}
# Fluxo inicial após adicionar expo-dev-clientnpx expo prebuild # pule se android/ e ios/ já existiremeas build --profile development --platform ios# Instale o build → depois diariamente:npx expo start --dev-client
O que isso demonstra:
registerDevMenuItems para diagnósticos específicos da equipe sem editar código nativo.
DevClient.openMenu() como um fallback programático para gestos de agitar.
eas.jsondevelopmentClient: true para que o EAS produza um binário de depuração com o launcher integrado.
Flag --dev-client para que o Metro nunca assuma que o Expo Go é o host.
expo-dev-client é um módulo nativo mais um plugin de configuração que integra uma UI de launcher, esquema de deep-link e menu dev aprimorado em builds de depuração.
Builds de desenvolvimento (binários de depuração com expo-dev-client) carregam JavaScript do Metro - a mesma história de Fast Refresh do Expo Go, mas o lado nativo é o ID do seu aplicativo, ícones e módulos instalados.
launchMode controla o cold start: most-recent entra no último URL do projeto; launcher mostra o seletor de servidor (útil para QA alternar ambientes).
defaultLaunchURL pula o seletor completamente quando definido - combine com substituições por plataforma para Android emulator (10.0.2.2) vs iOS simulator (localhost).
Alterações nativas (novo plugin de configuração, expo prebuild, edições de Gradle/Pod) exigem npx expo run:* ou eas build; alterações puras de JS/TS têm hot-reload via npx expo start --dev-client.
Proteja todas as APIs do dev-client com __DEV__ para que os builds de lançamento de produção façam tree-shake das chamadas (as APIs são no-ops em produção, mas a proteção mantém os bundles limpos).
Iniciar o Metro sem --dev-client - O CLI pode esperar pelo Expo Go ou mostrar o QR code errado. Correção: Sempre use npx expo start --dev-client depois que o projeto depender de expo-dev-client.
Editar a configuração do plugin app.json sem reconstruir - As configurações do launcher são em tempo de compilação. Correção: Execute npx expo run:* ou eas build após alterações no plugin.
Emulador Android não consegue alcançar localhost:8081 - O emulador mapeia o loopback do host para 10.0.2.2. Correção: Defina android.defaultLaunchURL para http://10.0.2.2:8081 ou use --lan.
registerDevMenuItems após hot reload duplica entradas - Os itens são anexados a cada registro. Correção: Registre uma vez em um guarda if (__DEV__ && !globalThis.__DEV_MENU__) no nível do módulo.
Esperando o Expo Go carregar módulos nativos personalizados - O Expo Go envia um binário fixo. Correção: Instale seu build de desenvolvimento; Native module cannot be null significa que você precisa de uma reconstrução.
Usar builds de desenvolvimento para testes de desempenho da loja - Clientes de desenvolvimento de depuração incluem ferramentas extras. Correção: Perfilar em builds preview ou de lançamento para métricas de FPS e inicialização.
Confusão do Expo Go no simulador iOS - O simulador ainda pode ter o Expo Go instalado ao lado do seu cliente de desenvolvimento. Correção: Abra o ícone correto do aplicativo (o nome do seu aplicativo, não "Expo Go").
Uma biblioteca e um plugin de configuração que adicionam um launcher de desenvolvimento, um menu dev aprimorado e ferramentas de depuração ao seu próprio binário de depuração de aplicativos - o nome do Expo para um "build de desenvolvimento".
Como instalo o expo-dev-client no SDK 57?
npx expo install expo-dev-client
Nunca fixe a versão manualmente - expo install resolve a versão compatível com SDK 57.
Por que devo executar expo start --dev-client?
A flag informa ao Expo CLI para gerar URLs e códigos QR para o seu binário personalizado. Sem ela, as ferramentas assumem que o Expo Go é o host de destino.
Qual a diferença entre launchMode most-recent e launcher?
most-recent abre o último URL do Metro diretamente (volta para o launcher se inacessível). launcher sempre mostra o seletor de servidor - melhor para QA alternar branches.
Quando preciso reconstruir o aplicativo nativo?
Após adicionar/remover módulos nativos, alterar plugins de configuração, editar ícones/splash/ID de bundle em app.json, ou atualizar o SDK Expo. Edições puras de JS têm hot-reload sem reconstrução.
Como adiciono botões personalizados ao menu dev?
import * as DevClient from "expo-dev-client";await DevClient.registerDevMenuItems([ { name: "Minha ação", callback: () => console.log("executar"), shouldCollapse: true },]);
Registre uma vez no início do aplicativo em __DEV__ apenas.
Como abro o menu dev sem agitar o telefone?
Pressione m no terminal do Metro, chame DevClient.openMenu() do JS, ou use o toque longo de três dedos nos simuladores iOS.
Posso usar expo-dev-client com Expo Router?
Sim - o template padrão do SDK 57 inclui o Router. O cliente dev carrega sua entrada do roteador (app/_layout.tsx) como qualquer outro aplicativo.
Qual perfil do eas.json compila um cliente dev?
Defina "developmentClient": true em um perfil de build (comumente chamado development). Execute eas build --profile development.
O expo-dev-client funciona em simuladores?
Sim. Use "ios": { "simulator": true } no perfil de desenvolvimento para IPAs de simulador, ou npx expo run:ios localmente.
Qual URL os emuladores Android devem usar para o Metro?
http://10.0.2.2:8081 - o alias do emulador para o localhost da máquina host. Defina android.defaultLaunchURL na configuração do plugin.
O expo-dev-client está incluído em builds de produção?
O shell nativo é o mesmo projeto, mas a UI do dev-client é removida dos builds de lançamento. Envie eas build --profile production para os binários da loja.
Como isso é diferente do Expo Go?
Expo Go é um aplicativo compartilhado com um conjunto fixo de módulos nativos. Um cliente de desenvolvimento é o binário do seu aplicativo com suas dependências nativas e identificador de bundle.
Armadilha: Native module cannot be null - e agora?
Instale expo-dev-client, reconstrua com npx expo run:android ou eas build --profile development, instale o novo binário e, em seguida, inicie o Metro com --dev-client.