-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[New Architecture][iOS][0.71.0] Update the App Migration section #3268
Merged
+92
−369
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,21 +13,29 @@ There are a few prerequisites that should be addressed before the New Architectu | |
|
||
React Native released the support for the New Architecture with the release `0.68.0`. | ||
|
||
This guide is written with the expectation that you’re using the latest React Native release. At the moment of writing, this is `0.70.0`. Besides this guide, you can leverage the [upgrade helper](https://react-native-community.github.io/upgrade-helper/) to determine what other changes may be required for your project. | ||
This guide is written with the expectation that you’re using the latest React Native release. At the moment of writing, this is `0.71.0`. Beside this guide, you can leverage the [upgrade helper](https://react-native-community.github.io/upgrade-helper/) to determine what other changes may be required for your project. | ||
|
||
To update to the most recent version of React Native, you can run this command: | ||
|
||
```bash | ||
yarn add react-native@0.70.0 | ||
npx react-native upgrade | ||
``` | ||
cipolleschi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Starting from React Native `0.69.0`, you may also need to update the version of React to 18. You can do so by using this command: | ||
## Use Hermes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I moved the
The new structure is
|
||
|
||
```bash | ||
yarn add react@18.0.0 | ||
``` | ||
Hermes is an open-source JavaScript engine optimized for React Native. Hermes is enabled by default, and you have to explicitly disable it if you want to use JSC. | ||
|
||
We highly recommend using Hermes in your application. With Hermes enabled, you can use the JavaScript debugger in Flipper to directly debug your JavaScript code. | ||
|
||
### Android Specifics | ||
Please [follow the instructions on the React Native website](hermes) to learn how to enable/disable Hermes. | ||
|
||
:::caution | ||
|
||
**iOS:** If you opt out of using Hermes, you will need to replace `HermesExecutorFactory` with `JSCExecutorFactory` in any examples used throughout the rest of this guide. | ||
|
||
::: | ||
|
||
## Android - Update Build System | ||
|
||
Using the New Architecture on Android has some prerequisites that you need to meet: | ||
|
||
|
@@ -149,63 +157,27 @@ dependencies { | |
+ implementation project(":ReactAndroid") // From node_modules | ||
``` | ||
|
||
## Use Hermes | ||
|
||
Hermes is an open-source JavaScript engine optimized for React Native. Hermes is enabled by default, and you have to explicitly disable it if you want to use JSC. | ||
|
||
We highly recommend using Hermes in your application. With Hermes enabled, you will be able to use the JavaScript debugger in Flipper to directly debug your JavaScript code. | ||
|
||
Please [follow the instructions on the React Native website](hermes) to learn how to enable/disable Hermes. | ||
|
||
:::caution | ||
|
||
**iOS:** If you opt-out of using Hermes, you will need to replace `HermesExecutorFactory` with `JSCExecutorFactory` in any examples used throughout the rest of this guide. | ||
## iOS - Build the Project | ||
|
||
::: | ||
|
||
### Android | ||
After upgrading the project, there are a few changes you need to apply: | ||
|
||
To enable Hermes in Android, open the `android/app/build.gradle` and apply the following changes: | ||
1. Target the proper iOS version. Open the `Podfile` and apply this change: | ||
|
||
```diff | ||
project.ext.react = [ | ||
- enableHermes: true, // clean and rebuild if changing | ||
+ enableHermes: true, // clean and rebuild if changing | ||
] | ||
// ... | ||
|
||
} | ||
|
||
if (enableHermes) { | ||
- def hermesPath = "../../node_modules/hermes-engine/android/"; | ||
- debugImplementation files(hermesPath + "hermes-debug.aar") | ||
- releaseImplementation files(hermesPath + "hermes-release.aar") | ||
+ //noinspection GradleDynamicVersion | ||
+ implementation("com.facebook.react:hermes-engine:+") { // From node_modules | ||
+ exclude group:'com.facebook.fbjni' | ||
+ } | ||
} else { | ||
``` | ||
|
||
Moreover, you'll need to update the `proguard-rules`, adding the following ones: | ||
|
||
``` | ||
-keep class com.facebook.hermes.unicode.** { *; } | ||
-keep class com.facebook.jni.** { *; } | ||
- platform :ios, '11.0' | ||
+ platform :ios, '12.4' | ||
``` | ||
|
||
After that, remember to cleanup the project, running | ||
2. Create an `.xcode.env` file to export the locaion of the NODE_BINARY. Navigate to the `ios` folder and run this command: | ||
|
||
```sh | ||
cd android | ||
./gradlew clean | ||
echo 'export NODE_BINARY=$(command -v node)' > .xcode.env | ||
``` | ||
|
||
## iOS: Build the Project | ||
|
||
After upgrading the project, there are a few changes you need to apply: | ||
If you need it, you can also open the file and replace the `$(command -v node)` with the path to the node executable. | ||
React Native also supports a local version of this file `.xcode.env.local`. This file is not synced with the repository to let you customize your local setup, if it differs from the Continuous Integration or the team one. | ||
|
||
1. Fix an API change in the `AppDelegate.m`. Open this file and apply this change: | ||
2. Fix an API change in the `AppDelegate.m`. Open this file and apply this change: | ||
|
||
```diff | ||
#if DEBUG | ||
|
@@ -214,67 +186,74 @@ After upgrading the project, there are a few changes you need to apply: | |
#else | ||
``` | ||
|
||
2. Target the proper iOS version. Open the `Podfile` and apply this change: | ||
## iOS - Use Objective-C++ (`.mm` extension) | ||
|
||
```diff | ||
- platform :ios, '11.0' | ||
+ platform :ios, '12.4' | ||
``` | ||
|
||
3. Create an `.xcode.env` file to export the locaion of the NODE_BINARY. Navigate to the `ios` folder and run this command: | ||
TurboModules can be written using Objective-C or C++. In order to support both cases, any source files that include C++ code should use the `.mm` file extension. This extension corresponds to Objective-C++, a language variant that allows for the use of a combination of C++ and Objective-C in source files. | ||
|
||
```sh | ||
echo 'export NODE_BINARY=$(command -v node)' > .xcode.env | ||
``` | ||
:::important | ||
|
||
If you need it, you can also open the file and replace the `$(command -v node)` with the path to the node executable. | ||
React Native also supports a local version of this file `.xcode.env.local`. This file is not synced with the repository to let you customize your local setup, if it differs from the Continuous Integration or the team one. | ||
**Use Xcode to rename existing files** to ensure file references persist in your project. You might need to clean the build folder (_Project → Clean Build Folder_) before re-building the app. If the file is renamed outside of Xcode, you may need to click on the old `.m` file reference and Locate the new file. | ||
|
||
## iOS: Use Objective-C++ (`.mm` extension) | ||
::: | ||
|
||
TurboModules can be written using Objective-C or C++. In order to support both cases, any source files that include C++ code should use the `.mm` file extension. This extension corresponds to Objective-C++, a language variant that allows for the use of a combination of C++ and Objective-C in source files. | ||
## iOS - Make your AppDelegate conform to `RCTAppDelegate` | ||
|
||
:::info | ||
The final step to configure iOS for the New Architecture is to extend a base class proided by React Native, called `RCTAppDelegate`. | ||
|
||
Use Xcode to rename existing files to ensure file references persist in your project. You might need to clean the build folder (_Project → Clean Build Folder_) before re-building the app. If the file is renamed outside of Xcode, you may need to click on the old `.m` file reference and Locate the new file. | ||
This class provides a base implementation for all the required functionalities of the new architecture. If you need to customize some of them, you can override those methods, invoke `[super methodNameWith:parameters:];` collecting the returned value and customize the bits you need to customize. | ||
|
||
::: | ||
1. Open the `ios/AppDelegate.h` file and update it as it follows: | ||
|
||
## iOS: TurboModules: Ensure your App Provides an `RCTCxxBridgeDelegate` | ||
```diff | ||
- #import <React/RCTBridgeDelegate.h> | ||
+ #import <React-RCTAppDelegate/RCTAppDelegate.h> | ||
#import <UIKit/UIKit.h> | ||
|
||
In order to set up the TurboModule system, you will add some code to interact with the bridge in your AppDelegate. Before you start, go ahead and rename your AppDelegate file to use the `.mm` extension. | ||
- @interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate> | ||
+ @interface AppDelegate : RCTAppDelegate | ||
|
||
Now you will have your AppDelegate conform to `RCTCxxBridgeDelegate`. Start by adding the following imports at the top of your AppDelegate file: | ||
- @property (nonatomic, strong) UIWindow *window; | ||
|
||
```objc | ||
#import <reacthermes/HermesExecutorFactory.h> | ||
#import <React/RCTCxxBridgeDelegate.h> | ||
#import <React/RCTJSIExecutorRuntimeInstaller.h> | ||
@end | ||
``` | ||
|
||
Then, declare your app delegate as a `RCTCxxBridgeDelegate` provider: | ||
2. Open the `ios/AppDelegate.mm` file and replace its content with the following: | ||
|
||
```objc | ||
@interface AppDelegate () <RCTCxxBridgeDelegate> { | ||
// ... | ||
#import "AppDelegate.h" | ||
#import <React/RCTBundleURLProvider.h> | ||
|
||
@implementation AppDelegate | ||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions | ||
{ | ||
self.moduleName = @"NameOfTheApp"; | ||
return [super application:application didFinishLaunchingWithOptions:launchOptions]; | ||
} | ||
|
||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge | ||
{ | ||
#if DEBUG | ||
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; | ||
#else | ||
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; | ||
#endif | ||
} | ||
|
||
- (BOOL)concurrentRootEnabled | ||
{ | ||
return true; | ||
} | ||
|
||
@end | ||
``` | ||
|
||
To conform to the `RCTCxxBridgeDelegate` protocol, you must implement the `jsExecutorFactoryForBridge:` method. Typically, this is where you would return a `JSCExecutorFactory` or `HermesExecutorFactory`, and we will use it to install our TurboModules bindings later on. | ||
|
||
You can implement the `jsExecutorFactoryForBridge:` method like this: | ||
:::note | ||
The `moduleName` has to be the same string used in the `[RCTRootView initWithBridge:moduleName:initialProperties]` call in the original `AppDelegate.mm` file. | ||
::: | ||
|
||
```objc | ||
#pragma mark - RCTCxxBridgeDelegate | ||
## iOS - Run pod install | ||
|
||
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge | ||
{ | ||
return std::make_unique<facebook::react::HermesExecutorFactory>(facebook::react::RCTJSIExecutorRuntimeInstaller([bridge](facebook::jsi::Runtime &runtime) { | ||
if (!bridge) { | ||
return; | ||
} | ||
}) | ||
); | ||
} | ||
```bash | ||
// Run pod install with the flags | ||
RCT_NEW_ARCH_ENABLED=1 pod install | ||
``` |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this should be backported to all the versions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ops... adressed in #3312