Loops locais de expo run:ios / expo run:android e a decisão de quando commitar ios/ e android/ em um fluxo de trabalho de Geração Nativa Contínua (Continuous Native Generation - CNG). Código nativo personalizado pertence a modules/, plugins de configuração e EAS Build - não a edições silenciosas no Xcode que desaparecem em um prebuild limpo.
# Estrutura um módulo Expo local (preferível a código de bridge bruto)npx create-expo-module@latest expo-device-info-plus# Mova para modules/ se a CLI criou uma pasta irmã
CustomNative/├── app.config.ts├── modules/│ └── expo-device-info-plus/ # Commite isso - fonte da verdade├── plugins/ # Commite plugins de configuração personalizados├── ios/ # Gitignore sob CNG└── android/ # Gitignore sob CNG
// App.tsximport * as DeviceInfoPlus from "expo-device-info-plus";import { useEffect, useState } from "react";import { Text, View } from "react-native";export default function App() { const [model, setModel] = useState<string>("…"); useEffect(() => { DeviceInfoPlus.getModelAsync().then(setModel); }, []); return ( <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}> <Text>Device model: {model}</Text> </View> );}
# Primeira compilação nativa em um clone recém-criadonpm installnpx expo run:ios# Após alterar Swift/Kotlin em modules/npx expo run:ios --no-build-cache
O que isso demonstra:
modules/ é commitado - o código nativo sobrevive a um prebuild limpo
ios//android/ são gerados - recriados a partir da configuração + autolinking em cada prebuild
expo run:ios orquestra prebuild → pod install → compilação Xcode
Alterações de módulo exigem recompilação - Fast Refresh não recarrega código nativo
npx expo prebuild --no-install# Verifique se o Podfile contém o script de autolinking do expo# Verifique se android/settings.gradle inclui useExpoModules()
Autolinking ausente se manifesta como módulo nativo indefinido em tempo de execução - não um erro do Metro.
# 1. Inventarie as diferenças do Xcode/Gradle em relação a um prebuild recém-criadorm -rf ios androidnpx expo prebuild --no-installgit diff # contra o antigo ios/ commitado# 2. Porte cada bloco de diff para um plugin de configuração ou alteração em modules/# 3. Portão final: prebuild limpo reproduz o comportamentorm -rf ios android && npx expo prebuild
Editar AppDelegate gerado sem um plugin - Perdido no prebuild limpo do SDK 57. Correção: Plugin expo-dev-client ou plugin de configuração personalizado.
Esperar que o Expo Go carregue módulos personalizados - O binário do Expo Go é fixo. Correção: Cliente de desenvolvimento via expo run:ios ou build de desenvolvimento EAS.
Esquecer de recompilar após alteração em Swift - O Metro Fast Refresh apenas atualiza o JS. Correção: Reexecute expo run:ios.
Duas cópias de react-native em monorepo - Autolinking escolhe a instância errada. Correção:npx expo-doctor, react-native unificado.
Committar ios/Pods/ - Bloat massivo do repositório e conflitos de merge. Correção: Gitignore Pods; pod install em CI/EAS.
Misturar CNG e Gradle editado manualmente - Prebuild sobrescreve edições não codificadas. Correção:expo-build-properties ou plugin personalizado.
Se ios/ estiver faltando, sim. Se ios/ existir, ele usa o projeto existente - que pode estar desatualizado. Após alterações nos plugins de configuração, execute npx expo prebuild ou exclua ios/ primeiro.
Onde o código Swift personalizado deve residir?
Em modules/<nome-do-modulo>/ios/ como um módulo Expo - o autolinking o conecta no prebuild. Evite editar ios/MyApp/ gerado diretamente sob CNG.
Posso usar o Xcode para depurar e depois mover as alterações para um plugin?
Sim - caminho comum de migração brownfield. Use expo prebuild --no-clean enquanto itera, depois verifique se um prebuild limpo reproduz o comportamento.
Como as bibliotecas nativas de terceiros se encaixam no CNG?