The expo package is more than a version pin - it bootstraps Expo Modules Core, the JSI-native runtime that registers Expo SDK modules, exposes requireNativeModule, and connects JavaScript to Swift/Kotlin implementations in every Expo and bare React Native app.
Wrong MainComponent name in bare apps - Native entry still says "MyApp" while JS registers "main". Fix: Set getMainComponentName() / moduleName to "main" or match your registerRootComponent name.
Missing autolinking after adding expo-camera - Native build never compiles the module. Fix: Run npx expo prebuild or verify expo-modules-autolinking in Gradle/Podfile; rebuild native.
Calling requireNativeModule in Expo Go for unbundled modules - Core works, but the native class was never shipped in Expo Go. Fix: Development build with the module installed.
Assuming bridge sync methods on fallback proxy - When JSI binding is missing, some sync APIs noop or throw. Fix: Rebuild with New Architecture enabled; verify module supports sync functions.
Importing from expo vs expo-modules-core - App authors can use either for requireNativeModule; library packages should import from expo-modules-core to avoid peer-dep cycles. Fix: Libraries → expo-modules-core; apps → expo re-exports.
Leaking SharedObjects - Long-lived native handles (video players) retain memory until release() or hook cleanup. Fix: Use package hooks (useVideoPlayer) or call release() when done.
The native + JavaScript infrastructure behind the Expo Modules API. It registers native modules on a JSI host object, exposes requireNativeModule, and provides NativeModule, EventEmitter, and SharedObject primitives used by every expo-* package.
How is the expo package different from expo-modules-core?
expo is the umbrella runtime - registerRootComponent, isRunningInExpoGo, web polyfills, and re-exports. expo-modules-core is the low-level module loader and type layer library authors depend on.
What does registerRootComponent do?
It calls AppRegistry.registerComponent("main", …), sets up web rendering, polyfills process.nextTick, and enables dev-only Fast Refresh helpers. Every Expo app ultimately registers "main" as the root component name.
How does requireNativeModule find native code?
It queries the JSI host object populated at native launch. If absent, it falls back to a bridge proxy module - still functional but missing some synchronous JSI methods.
Why do I get Cannot find native module ExpoSomething?
Common causes: native project not rebuilt after install, autolinking misconfigured in bare app, module not included in Expo Go, or typo in module name. Rebuild native and verify with npx expo-modules-autolinking resolve.
Does Expo Modules Core require Expo Go?
No. It runs in development builds, production binaries, and bare React Native apps once autolinking and the "main" entry name are configured.
How does this relate to the New Architecture?
Expo modules are JSI-first and support TurboModules/Fabric. SDK 57 defaults to New Architecture on RN 0.86; Core handles both paths with bridge fallback for older setups.
What is a SharedObject?
A JSI-backed native instance with methods and events - e.g. a video player. It extends EventEmitter and persists across JS calls until release() or hook teardown.
Gotcha: Why do high-level imports work but requireNativeModule fails?
You may be in Expo Go where the high-level JS package exists but the native module is not bundled, or the native name differs (ExpoDevice vs Device). Verify the exact native module name in the package docs and use a development build.
Can I use Expo Modules in a brownfield app?
Yes. Run npx install-expo-modules, align the root component name, rebuild native, and install SDK packages with npx expo install.
What is expo-modules-autolinking?
Build-time tooling that scans dependencies and wires Gradle/Podspec entries so native Expo modules compile into your app without manual linking.
How do native events reach JavaScript?
NativeModule extends EventEmitter. Native code emits events; JS subscribes via addListener, useEventListener, or useEvent from expo.
Should library code import from expo or expo-modules-core?
Library packages should depend on expo-modules-core for requireNativeModule to avoid circular peers. Application code may import from expo for ergonomics.
Does expo bundle global fetch in SDK 57?
Yes. SDK 57 installs WinterCG-compliant fetch globally on native unless EXPO_PUBLIC_USE_RN_FETCH=1 is set. Named import { fetch } from 'expo/fetch' always uses the Expo implementation.