feat(ios): support bundled JS in debug builds#317
Conversation
- Added a method to configure the development loading view based on the debug settings. - Introduced `BrownfieldDevLoadingViewBridge` to manage the loading view state. - Updated `BrownfieldAppleApp` to prefer bundled bundles in debug mode. - Adjusted `ExpoHostRuntime` and `ReactNativeHostRuntime` to call the new configuration method.
artus9033
left a comment
There was a problem hiding this comment.
Amazing work! Left some comments for naming conventions & few questions, LGTM after they are resolved.
| | `entryFile` | `NSString` | `index` | Path to JavaScript entry file in development. | | ||
| | `bundlePath` | `NSString` | `main.jsbundle` | Path to JavaScript bundle file. | | ||
| | `bundle` | `NSBundle` | `Bundle.main` | Bundle instance to lookup the JavaScript bundle resource. | | ||
| | `preferBundledBundleInDebug` | `BOOL` | `NO` | Prefer the embedded JavaScript bundle instead of Metro when the framework is built in Debug. | |
There was a problem hiding this comment.
It's a bit of a tongue twister ;) let's rename this to preferEmbeddedBundleInDebug
| | `entryFile` | `String` | `index` | Path to JavaScript entry file in development. | | ||
| | `bundlePath` | `String` | `main.jsbundle` | Path to JavaScript bundle file. | | ||
| | `bundle` | `Bundle` | `Bundle.main` | Bundle instance to lookup the JavaScript bundle resource. | | ||
| | `preferBundledBundleInDebug` | `Bool` | `false` | Prefer the embedded JavaScript bundle instead of Metro when the framework is built in Debug. | |
| npx react-native start | ||
| ``` | ||
|
|
||
| If you want to run a **Debug-built** framework without Metro, enable the bundled bundle explicitly before calling `startReactNative`: |
There was a problem hiding this comment.
I'd add a ## Embedded bundle in Development section here
| interface BrownfieldNavigationDelegate { | ||
| fun navigateToSettings() | ||
| fun navigateToReferrals(userId: String) | ||
| } |
There was a problem hiding this comment.
This is codegen-ed and should not be committed :)
| override fun navigateToSettings() { | ||
| BrownfieldNavigationManager.getDelegate().navigateToSettings() | ||
| } | ||
|
|
||
| @ReactMethod | ||
| override fun navigateToReferrals(userId: String) { | ||
| BrownfieldNavigationManager.getDelegate().navigateToReferrals(userId) |
| @@ -0,0 +1,26 @@ | |||
| import Foundation | |||
|
|
|||
| enum BrownfieldBundleURLResolver { | |||
There was a problem hiding this comment.
How about we make that a class?
| let package = Package( | ||
| name: "BrownfieldBundleSupport", | ||
| platforms: [ | ||
| .macOS(.v13), | ||
| ], |
There was a problem hiding this comment.
Are you sure we need this here? It may be a tad confusing to look at the ios folder with this macos package def. Can we move it to a subdir?
| * Prefer the embedded JavaScript bundle instead of Metro when this framework is built in Debug. | ||
| * Default value: false | ||
| */ | ||
| public var preferBundledBundleInDebug: Bool = false { |
| var entryFile = "index" | ||
| var bundlePath = "main.jsbundle" | ||
| var bundle = Bundle.main | ||
| var preferBundledBundleInDebug = false |
| DYLIB_INSTALL_NAME_BASE: '"@rpath"', | ||
| INSTALL_PATH: '"$(LOCAL_LIBRARY_DIR)/Frameworks"', |
There was a problem hiding this comment.
Won't we need the same in non-Expo (RNC CLI) workflow?
Summary
Fixes iOS Debug packaged-bundle loading for brownfield apps running without Metro.
This PR addresses the case where a consumed brownfield XCFramework is built in
Debugand the host app wants to load the packaged JavaScript bundle instead of relying on a dev server.Root cause
There were two separate issues:
Debug, the iOS runtime always preferred Metro and ignored the embeddedmain.jsbundleDebug, the simulator slice of the packagedBrownfieldLib.xcframeworkdid not containmain.jsbundleWhat changed
Runtime
preferBundledBundleInDebugtoReactNativeBrownfieldpreferBundledBundleInDebug = true, Debug builds load the embedded bundlebundleURLOverridefallback behavior when the override returnsnilPackaging
main.jsbundlefrom the device framework build product into the simulator framework build productBrownfieldLib.xcframeworkso the simulator slice also containsmain.jsbundleValidation / coverage
iOS native testsCI job for Swift-based iOS testsRepro note
This issue only reproduces when the consumed XCFrameworks are themselves built in
Debug.A
Debughost app linked againstRelease-built XCFrameworks is a false negative, because the framework runtime has already been compiled without the Debug Metro branch.Validation
swift testinpackages/react-native-brownfield/iosyarn workspace @callstack/brownfield-cli test src/brownfield/utils/__tests__/copy-debug-bundle-to-simulator-slice.test.tsyarn exec brownfield package:ios --scheme BrownfieldLib --configuration DebugDebug-iphonesimulator/BrownfieldLib.framework/main.jsbundleexistsBrownfieldLib.xcframework/ios-arm64_x86_64-simulator/BrownfieldLib.framework/main.jsbundleexistsUser impact
Host apps can now explicitly opt into running a Debug-built brownfield framework from the packaged bundle:
With the normal Debug packaging flow, the packaged simulator XCFramework now includes the bundle needed for that opt-in to work without Metro.