feat(iOS): allow eager initialization of RCTRootViewFactory (#49986)

Summary:
Expose eager initialization method on `RCTRootViewFactory` (iOS) so that application can prepare `ReactHost`/Bridge before actually creating a root view. Then creating a root view is significantly faster.

## Changelog:
[IOS] [ADDED] - allow eager initialization of `RCTRootViewFactory`

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests

Pull Request resolved: https://github.com/facebook/react-native/pull/49986

Test Plan:
Invoke `initializeReactHostWithLaunchOptions:` before calling `viewWithModuleName:` and measure the time difference vs not using eager initilization:

Before
- calling `viewWithModuleName:`: 63.39ms, 47.91 ms, 60.18ms

After:
- calling `initializeReactHostWithLaunchOptions`: 52.41 ms, 81.03 ms, 60.52 ms
- calling `viewWithModuleName`: 0.49 ms,  0.63 ms, 0.47 ms

Test run 3 times on iPhone simulator on M1 mac.

Reviewed By: javache

Differential Revision: D71548601

Pulled By: cipolleschi

fbshipit-source-id: 86ecfb8bec4c2657537caf32af49545b21d3656b
This commit is contained in:
Maciej Jastrzębski
2025-03-20 09:52:53 -07:00
committed by Facebook GitHub Bot
parent a8745324c6
commit ddbb5fda09
2 changed files with 23 additions and 6 deletions
@@ -212,6 +212,15 @@ typedef void (^RCTLoadSourceForBridgeBlock)(RCTBridge *bridge, RCTSourceLoadBloc
#pragma mark - RCTRootViewFactory Helpers
/**
* Initialize React Host/Bridge without creating a view.
*
* Use it to speed up later viewWithModuleName: calls.
*
* @parameter: launchOptions - a dictionary with a set of options.
*/
- (void)initializeReactHostWithLaunchOptions:(NSDictionary *__nullable)launchOptions;
- (RCTHost *)createReactHost:(NSDictionary *__nullable)launchOptions;
@end
@@ -132,9 +132,7 @@
return [self viewWithModuleName:moduleName initialProperties:nil launchOptions:nil];
}
- (UIView *)viewWithModuleName:(NSString *)moduleName
initialProperties:(NSDictionary *)initProps
launchOptions:(NSDictionary *)launchOptions
- (void)initializeReactHostWithLaunchOptions:(NSDictionary *)launchOptions
{
if (_configuration.bridgelessEnabled) {
// Enable TurboModule interop by default in Bridgeless mode
@@ -142,7 +140,20 @@
RCTEnableTurboModuleInteropBridgeProxy(YES);
[self createReactHostIfNeeded:launchOptions];
return;
}
[self createBridgeIfNeeded:launchOptions];
[self createBridgeAdapterIfNeeded];
}
- (UIView *)viewWithModuleName:(NSString *)moduleName
initialProperties:(NSDictionary *)initProps
launchOptions:(NSDictionary *)launchOptions
{
[self initializeReactHostWithLaunchOptions:launchOptions];
if (_configuration.bridgelessEnabled) {
RCTFabricSurface *surface = [self.reactHost createSurfaceWithModuleName:moduleName initialProperties:initProps];
RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView =
@@ -155,9 +166,6 @@
return surfaceHostingProxyRootView;
}
[self createBridgeIfNeeded:launchOptions];
[self createBridgeAdapterIfNeeded];
UIView *rootView;
if (_configuration.createRootViewWithBridge != nil) {
rootView = _configuration.createRootViewWithBridge(self.bridge, moduleName, initProps);