feat: Expo support (managed workflow, dev-client, and bare) for iOS and Android - #45
Open
eumaninho54 wants to merge 4 commits into
Open
feat: Expo support (managed workflow, dev-client, and bare) for iOS and Android#45eumaninho54 wants to merge 4 commits into
eumaninho54 wants to merge 4 commits into
Conversation
Derives the sandbox's dev bundle URL in JS from the host's own resolved script URL (NativeModules.SourceCode.scriptURL) instead of guessing it natively. Works the same regardless of which launcher stood up the host (RN CLI, Expo dev-client, bare), so Expo managed workflow works out of the box with no native changes.
Pulled apps/expo-demo in from upstream PR callstackincubator#42 (Expo managed workflow demo with expo-dev-client). Bumped @types/react to match the workspace version and fix a duplicate-types JSX error.
Under New Architecture / bridgeless, NativeModules.SourceCode doesn't come with constants pre-flattened onto the object, only a getConstants() method. Confirmed working end to end on iOS and Android in an Expo managed workflow app with expo-dev-client.
downloadRemoteBundle reused a cached copy of any http(s) bundle by URL, but a dev bundle served by Metro (identified by dev=true in the query string) changes content without the URL changing. Only remote bundles without dev=true (e.g. a CDN-hosted production bundle) still use the cache. Confirmed on device: edited sandbox JS, reloaded without a native rebuild, sandbox picked up the change instead of serving stale JS.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Expo support (managed workflow with
expo-dev-client, and bare) on both iOS and Android, in dev and production builds. Related to #13.Two other approaches were already attempted for this (#42, #15). This PR takes a different path: instead of resolving the sandbox's bundle URL natively during boot, it resolves it in JS, after the host is already running.
The problem
In dev, the sandbox needs to know the Metro URL to fetch its own bundle. On RN CLI,
RCTBundleURLProvideralready has this because it's the same code that booted the host. Under Expo's dev-client, a different launcher (expo-dev-launcher) resolves that URL instead, soRCTBundleURLProvidernever gets configured, and the sandbox has nothing to read from.#42 solves this by reaching into
EXDevLauncherControllerat runtime (objc_getClass/performSelector, no compile-time header dependency) and using KVO to wait forsourceUrlto become available, since it's set asynchronously a second or two after launch. It's iOS-only, gated behind#if DEBUG, and the derived query string is hardcoded (platform=ios&dev=true&hot=false), so it doesn't track the actual dev state.#15 takes a different angle: swap between
ExpoReactNativeFactoryDelegateandRCTDefaultReactNativeFactoryDelegatevia#ifdef EXPO_MODULE, linkingExpoModulesCoreconditionally. That solves a different piece (which native factory to use for a bare Expo app) but doesn't actually derive the dev Metro URL. It's also iOS-only and never finished.This approach
The sandbox's bundle URL is resolved in JS, using
NativeModules.SourceCode.getConstants().scriptURLfrom the host that's already running. That value always reflects wherever the host bundle actually loaded from, no matter which launcher resolved it (RN CLI,expo-dev-launcher, whatever comes next). Since JS only runs after the host has booted, there's no timing race to work around, and no dependency on Expo's internal classes.platform,dev,hot,minify, etc.), reading them from the host's actual URL instead of hardcoding them, so it doesn't break under--no-devor similartransform.routerRoot) that would otherwise break the sandbox bundleAlso fixed along the way
NativeModules.SourceCodedoesn't come with its constants pre-flattened under New Architecture/bridgeless, only agetConstants()method. Needed for the above to actually work.Test plan
Added
apps/expo-demo(from #42, adjusted for this fork).