O pacote expo é mais do que um pino de versão - ele inicializa o Expo Modules Core, o runtime nativo JSI que registra os módulos do SDK Expo, expõe requireNativeModule e conecta JavaScript a implementações Swift/Kotlin em todos os apps Expo e React Native bare.
Cartão de receita de referência rápida - pronto para copiar e colar.
// index.ts (ponto de entrada customizado) ou root do App.tsximport { registerRootComponent } from "expo";import { requireNativeModule, requireOptionalNativeModule } from "expo-modules-core";import App from "./App";// Opcional: sonda um módulo nativo na inicialização (diagnóstico de dev)const ExpoDevice = requireOptionalNativeModule("ExpoDevice");if (__DEV__ && ExpoDevice) { console.log("Módulo nativo ExpoDevice carregado via JSI");}registerRootComponent(App);
# Garanta que o pacote core corresponda ao SDK 57npx expo install expo expo-modules-core
Quando usar isso:
Para entender por que import { Camera } from 'expo-camera' funciona após apenas npx expo install.
Para depurar Cannot find native module 'Expo…' em configurações bare ou brownfield.
Para chamar requireNativeModule de bibliotecas compartilhadas sem componentes React.
Para criar ou integrar módulos nativos construídos com a Expo Modules API.
Registra o componente root como "main"; entrada web + helpers de dev
requireNativeModule(name)
Carrega o módulo nativo; lança erro se ausente
requireOptionalNativeModule(name)
O mesmo, retorna null quando ausente
requireNativeView
Substituição direta para requireNativeComponent
NativeModule
Classe base para módulos nativos; estende EventEmitter
SharedObject / SharedRef
Handles nativos de longa duração (players de vídeo, refs de imagem) via JSI
isRunningInExpoGo()
Verificação de runtime para Expo Go vs binário customizado
import { EventEmitter, requireNativeModule } from "expo-modules-core";// Métodos NativeModule são assíncronos por padrão, a menos que marcados como síncronos no código nativoconst module = requireNativeModule("ExpoFileSystem");
Nome incorreto de MainComponent em apps bare - A entrada nativa ainda diz "MyApp" enquanto o JS registra "main". Correção: Defina getMainComponentName() / moduleName para "main" ou o nome do seu registerRootComponent.
Autolinking ausente após adicionar expo-camera - O build nativo nunca compilou o módulo. Correção: Execute npx expo prebuild ou verifique expo-modules-autolinking no Gradle/Podfile; reconstrua o nativo.
Chamar requireNativeModule no Expo Go para módulos não empacotados - O Core funciona, mas a classe nativa nunca foi incluída no Expo Go. Correção: Build de desenvolvimento com o módulo instalado.
Assumir métodos síncronos de bridge no proxy de fallback - Quando o binding JSI está ausente, algumas APIs síncronas não fazem nada ou lançam erro. Correção: Reconstrua com a Nova Arquitetura habilitada; verifique se o módulo suporta funções síncronas.
Importar de expo vs expo-modules-core - Autores de apps podem usar qualquer um para requireNativeModule; pacotes de bibliotecas devem importar de expo-modules-core para evitar ciclos de dependência entre pares. Correção: Bibliotecas → expo-modules-core; apps → expo re-exports.
Vazamento de SharedObjects - Handles nativos de longa duração (players de vídeo) retêm memória até release() ou limpeza de hook. Correção: Use hooks do pacote (useVideoPlayer) ou chame release() quando terminar.
Pular npx expo install - Versões npm manuais não correspondem aos binários nativos vs stubs JS. Correção: Sempre use npx expo install <pkg> para que o autolinking resolva builds compatíveis com SDK 57.
A infraestrutura nativa + JavaScript por trás da Expo Modules API. Ela registra módulos nativos em um objeto host JSI, expõe requireNativeModule e fornece primitivas NativeModule, EventEmitter e SharedObject usadas por todos os pacotes expo-*.
Como o pacote expo difere do expo-modules-core?
expo é o runtime guarda-chuva - registerRootComponent, isRunningInExpoGo, polyfills web e re-exports. expo-modules-core é o carregador de módulos de baixo nível e a biblioteca de tipos na qual os autores dependem.
O que faz registerRootComponent?
Ele chama AppRegistry.registerComponent("main", …), configura a renderização web, polyfills process.nextTick e habilita helpers de Fast Refresh apenas para desenvolvimento. Todo app Expo eventualmente registra "main" como o nome do componente root.
Como requireNativeModule encontra o código nativo?
Ele consulta o objeto host JSI preenchido no lançamento nativo. Se ausente, ele recorre a um módulo proxy de bridge - ainda funcional, mas carecendo de alguns métodos JSI síncronos.
Por que recebo Cannot find native module ExpoSomething?
Causas comuns: projeto nativo não reconstruído após a instalação, autolinking mal configurado em app bare, módulo não incluído no Expo Go, ou erro de digitação no nome do módulo. Reconstrua o nativo e verifique com npx expo-modules-autolinking resolve.
O Expo Modules Core requer o Expo Go?
Não. Ele roda em builds de desenvolvimento, binários de produção e apps React Native bare após a configuração do autolinking e o nome de entrada "main".
Como isso se relaciona com a Nova Arquitetura?
Os módulos Expo são JSI-first e suportam TurboModules/Fabric. O SDK 57 usa a Nova Arquitetura por padrão no RN 0.86; o Core lida com ambos os caminhos com fallback de bridge para configurações mais antigas.
O que é um SharedObject?
Uma instância nativa baseada em JSI com métodos e eventos - por exemplo, um player de vídeo. Ele estende EventEmitter e persiste entre chamadas JS até release() ou o fim do hook.
Armadilha: Por que imports de alto nível funcionam, mas requireNativeModule falha?
Você pode estar no Expo Go, onde o pacote JS de alto nível existe, mas o módulo nativo não está empacotado, ou o nome nativo é diferente (ExpoDevice vs Device). Verifique o nome exato do módulo nativo na documentação do pacote e use um build de desenvolvimento.
Posso usar Expo Modules em um app brownfield?
Sim. Execute npx install-expo-modules, alinhe o nome do componente root, reconstrua o nativo e instale os pacotes do SDK com npx expo install.
O que é expo-modules-autolinking?
Ferramenta de build que escaneia dependências e conecta entradas Gradle/Podspec para que os módulos nativos Expo sejam compilados em seu app sem link manual.
Como eventos nativos chegam ao JavaScript?
NativeModule estende EventEmitter. O código nativo emite eventos; o JS se inscreve via addListener, useEventListener, ou useEvent do expo.
O código da biblioteca deve importar de expo ou expo-modules-core?
Pacotes de biblioteca devem depender de expo-modules-core para requireNativeModule para evitar pares circulares. O código da aplicação pode importar de expo por conveniência.
O expo empacota o fetch global no SDK 57?
Sim. O SDK 57 instala o fetch compatível com WinterCG globalmente no nativo, a menos que EXPO_PUBLIC_USE_RN_FETCH=1 seja definido. import { fetch } from 'expo/fetch' sempre usa a implementação Expo.