diff --git a/docs/build-speed.md b/docs/build-speed.md index 69d74a10b4c..2fa1f1b763f 100644 --- a/docs/build-speed.md +++ b/docs/build-speed.md @@ -6,22 +6,21 @@ title: Speeding up your Build phase Building your React Native app could be **expensive** and take several minutes of developers time. This can be problematic as your project grows and generally in bigger organizations with multiple React Native developers. -With [the New React Native Architecture](new-architecture-app-intro), this problem is becoming more critical -as you might have to compile some native C++ code in your project with the Android NDK in addition to the native code already necessary for the iOS and Android platforms. - To mitigate this performance hit, this page shares some suggestions on how to **improve your build time**. +:::info +If you're noticing slower build time with the **New Architecture on Android**, we recommend to upgrade to React Native 0.71 +::: + ## Build only one ABI during development (Android-only) When building your android app locally, by default you build all the 4 [Application Binary Interfaces (ABIs)](https://developer.android.com/ndk/guides/abis) : `armeabi-v7a`, `arm64-v8a`, `x86` & `x86_64`. However, you probably don't need to build all of them if you're building locally and testing your emulator or on a physical device. -This should reduce your build time by a **~75% factor**. +This should reduce your **native build time** by a ~75% factor. -If you're using the React Native CLI, you can use the `--active-arch-only` flag together with the `run-android` command. -This flag will make sure the correct ABI is picked up from either the running emulator or the plugged in phone. -To confirm that this approach is working fine, you'll see a message like `info Detected architectures arm64-v8a` on console. +If you're using the React Native CLI, you can add the `--active-arch-only` flag to the `run-android` command. This flag will make sure the correct ABI is picked up from either the running emulator or the plugged in phone. To confirm that this approach is working fine, you'll see a message like `info Detected architectures arm64-v8a` on console. ``` $ yarn react-native run-android --active-arch-only diff --git a/docs/new-architecture-app-intro.md b/docs/new-architecture-app-intro.md index 72e9f7f0c0a..479da51b114 100644 --- a/docs/new-architecture-app-intro.md +++ b/docs/new-architecture-app-intro.md @@ -11,17 +11,13 @@ import constants from '@site/core/TabsConstants'; There are a few prerequisites that should be addressed before the New Architecture is enabled in your application. -## Use a React Native >= 0.68 Release +## Update to the latest React Native version 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.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. +This guide is written with the expectation that you’re using the [**latest** React Native release](https://github.com/facebook/react-native/releases/latest). -To update to the most recent version of React Native, you can run this command: - -```bash -npx react-native upgrade -``` +You can find instructions on how to upgrade in the page [upgrading to new versions](/docs/upgrading). ## Use Hermes @@ -29,7 +25,7 @@ Hermes is an open-source JavaScript engine optimized for React Native. Hermes is 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. -Please [follow the instructions on the React Native website](hermes) to learn how to enable/disable Hermes. +Please [follow the instructions on the Hermes page](hermes) to learn how to enable/disable Hermes. :::caution @@ -140,328 +136,20 @@ RCT_NEW_ARCH_ENABLED=1 pod install ## Android - Prerequisites -Using the New Architecture on Android has some prerequisites that you need to meet: - -1. Using Gradle version >= 7.x -2. Using Android Gradle Plugin >= 7.3.x (i.e. the `com.android.tools.build:gradle` dependency) - -If you updated to React Native 0.68+, you already meet those prerequisites. If you don't meet them, consider updating those dependencies first. - -## Android - React Native Gradle Plugin & Build from Source - -The New Architecture relies on the React Native Gradle Plugin (from the `react-native-gradle-plugin` NPM package) to build and run your project. - -Moreover, in this iteration of the guide you will build React Native from source. - -If you updated your project to React Native 0.68+, you probably already have this configuration set up correctly. - -If not make sure you edit the `android/settings.gradle` file as follows: - -```diff - rootProject.name = 'HelloWorld' - apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) - include ':app' -+includeBuild('../node_modules/react-native-gradle-plugin') - -+include(":ReactAndroid") -+project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid') -+include(":ReactAndroid:hermes-engine") -+project(":ReactAndroid:hermes-engine").projectDir = file('../node_modules/react-native/+ReactAndroid/hermes-engine') -``` - -Update the `android/build.gradle` file as follows: - -```diff -buildscript { - // ... - dependencies { - - // Add those lines -+ classpath("com.facebook.react:react-native-gradle-plugin") -+ classpath("de.undercouch:gradle-download-task:4.1.2") - } -} -``` +If you successfully updated your project to React Native `0.71.0`, you **already meet** all the prerequisites to use the New Architecture on Android. -And update the `android/app/build.gradle` file (please note that this file is different than the top level `build.gradle`) as follows: +You will only need to update your `android/gradle.properties` file as follows: ```diff -dependencies { - // ... - 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 - } -} - -+ configurations.all { -+ resolutionStrategy.dependencySubstitution { -+ substitute(module("com.facebook.react:react-native")) -+ .using(project(":ReactAndroid")) -+ .because("On New Architecture we're building React Native from source") -+ substitute(module("com.facebook.react:hermes-engine")) -+ .using(project(":ReactAndroid:hermes-engine")) -+ .because("On New Architecture we're building Hermes from source") -+ } -+ } -``` - -## Android - Configure the NDK - -:::caution - -In this iteration of the guide you’re setting up the project to build from source. You might notice an increase in your build time because of this. -You can mitigate this by following the approach described in [Speeding up your Build phase](/docs/next/build-speed) guide. - -::: - -As Codegen will output some Java and some C++ code that needs to build, you need to configure the Android NDK to do so. - -Edit your `android/app/build.gradle` file to include the **two** `externalNativeBuild` blocks detailed below inside the `android{}` block: - -```groovy -android { - defaultConfig { - applicationId "com.awesomeproject" - // ... - - // Add this block - externalNativeBuild { - cmake { - arguments "-DPROJECT_BUILD_DIR=$buildDir", - "-DREACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid", - "-DREACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build", - "-DANDROID_STL=c++_shared" - } - } - } - - // Add this block - externalNativeBuild { - cmake { - path "$projectDir/src/main/jni/CMakeLists.txt" - } - } -} -``` - -Finally, you need to create two files that are required to build the native code correctly: - -- A CMake file with the compilation instructions (similar to a `build.gradle` for Android/Java) -- An `OnLoad.cpp` file which, as the name says, will be loaded when your app starts. - -Create a file inside the `android/app/src/main/jni` folder called `CMakeLists.txt` with the following content: - -```cmake title="CMakeLists.txt" -cmake_minimum_required(VERSION 3.13) - -# Define the library name here. -project(appmodules) - -# This file includes all the necessary to let you build your application with the New Architecture. -include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake) +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +-newArchEnabled=false ++newArchEnabled=true ``` -And create the `android/app/src/main/jni/OnLoad.cpp` file with the following content: - -```cpp title="OnLoad.cpp" -#include -#include -#include -#include -#include - -namespace facebook { -namespace react { - -void registerComponents( - std::shared_ptr registry) { - // Custom Fabric Components go here. You can register custom - // components coming from your App or from 3rd party libraries here. - // - // providerRegistry->add(concreteComponentDescriptorProvider< - // AocViewerComponentDescriptor>()); - - // By default we just use the components autolinked by RN CLI - rncli_registerProviders(registry); -} - -std::shared_ptr provideModules( - const std::string &name, - const JavaTurboModule::InitParams ¶ms) { - // Here you can provide your own module provider for TurboModules coming from - // either your application or from external libraries. The approach to follow - // is similar to the following (for a library called `samplelibrary`): - // - // auto module = samplelibrary_ModuleProvider(moduleName, params); - // if (module != nullptr) { - // return module; - // } - // return rncore_ModuleProvider(moduleName, params); - - // By default we just use the module providers autolinked by RN CLI - return rncli_ModuleProvider(name, params); -} - -} // namespace react -} // namespace facebook - -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { - return facebook::jni::initialize(vm, [] { - facebook::react::DefaultTurboModuleManagerDelegate:: - moduleProvidersFromEntryPoint = &facebook::react::provideModules; - facebook::react::DefaultComponentsRegistry:: - registerComponentDescriptorsFromEntryPoint = - &facebook::react::registerComponents; - }); -} -``` - -When the app loads, this file will take care of registering the Native Components and Modules which provide native sources. By default we only provide the autolinked libraries as this allows you to use those libraries. - -This is the only C++ file you'll have to add to your project, and the infrastructure will take care of the rest. - -## Android - Update your Java classes - -To simplify how to enable the New Architecture on Android, you can use some utility classes that will take care of all the setup without you having to worry about it. - -Those classes are all located inside the `com.facebook.react.defaults` package and are all named `Defaults*`. - -### Update the React Native Host - -First, update your `ReactNativeHost` as follows (usually located in your `MainApplication.java` file): - - - - -```diff title="MainApplication.java" -+import com.facebook.react.defaults.DefaultReactNativeHost; - - private final ReactNativeHost mReactNativeHost = -- new ReactNativeHost(this) { -+ new DefaultReactNativeHost(this) { - - @Override - public boolean getUseDeveloperSupport() { - return BuildConfig.DEBUG; - } - -+ @Override -+ public boolean isNewArchEnabled() { -+ return true; -+ } -``` - - - - -```diff title="MainApplication.kt" -+import com.facebook.react.defaults.DefaultReactNativeHost - - val reactNativeHost = -- ReactNativeHost(this) { -+ DefaultReactNativeHost(this) { - - override fun getUseDeveloperSupport() = BuildConfig.DEBUG -+ override fun isNewArchEnabled() = true - - } -``` - - - - -### Update the your application OnCreate - -Still inside your `MainApplication` method `onCreate`, make sure that the New Architecture infrastructure is loaded correctly: - - - - -```diff title="MainApplication.java" -+import com.facebook.react.defaults.DefaultNativeEntryPoint; - - @Override - public void onCreate() { - super.onCreate(); - SoLoader.init(this, /* native exopackage */ false); - // Make sure it's called after SoLoader.init -+ ReactFeatureFlags.useTurboModules = true; -+ DefaultNativeEntryPoint.load(); - ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - } -``` - - - - -```diff title="MainApplication.kt" -+import com.facebook.react.defaults.DefaultNativeEntryPoint - - override fun onCreate() { - super.onCreate() - SoLoader.init(this, /* native exopackage */ false) - // Make sure it's called after SoLoader.init -+ ReactFeatureFlags.useTurboModules = true -+ DefaultNativeEntryPoint.load() - ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - } -``` - - - - -### Update your Activity Delegate - -Finally, update your `MainActivity.java` file by providing a React Activity Delegate: - - - - -```diff title="MainActivity.java" -+import com.facebook.react.defaults.DefaultReactActivityDelegate; - -public class MainActivity extends ReactActivity { - -+ @Override -+ protected ReactActivityDelegate createReactActivityDelegate() { -+ return new DefaultReactActivityDelegate( -+ this, -+ getMainComponentName(), -+ true, // Here we enable Fabric -+ true, // Here we enable Concurrent React Features -+ ); -+ } - -} -``` - - - - -```diff title="MainApplication.kt" -+import com.facebook.react.defaults.DefaultReactActivityDelegate; - -public class MainActivity : ReactActivity { - -+ @Override -+ override protected fun createReactActivityDelegate() = -+ DefaultReactActivityDelegate( -+ this, -+ mainComponentName, -+ true, // Here we enable Fabric -+ true, // Here we enable Concurrent React Features -+ ) - -} -``` - - - - That's it! It’s now time to run your Android app to verify that everything works correctly: diff --git a/docs/new-architecture-library-intro.md b/docs/new-architecture-library-intro.md index 4f0a3750dd5..13b6d5016df 100644 --- a/docs/new-architecture-library-intro.md +++ b/docs/new-architecture-library-intro.md @@ -156,7 +156,7 @@ If your existing native module has methods with the same name on multiple platfo ### Android -On Android, this generally requires you to include `native_modules.gradle` in both your `settings.gradle[.kts]` and `build.gradle[.kts]`. +On Android, this generally requires you to include `native_modules.gradle` in both your `settings.gradle` and `build.gradle`. If you used the default template provided with React Native (i.e., `yarn react-native init `), then autolinking is already enabled. diff --git a/docs/new-architecture-troubleshooting.md b/docs/new-architecture-troubleshooting.md index 09bd0e6dc93..78eb1aea78e 100644 --- a/docs/new-architecture-troubleshooting.md +++ b/docs/new-architecture-troubleshooting.md @@ -57,7 +57,6 @@ Make sure to uncomment the line and set the preferred memory size with the `-Xmx ## Android NDK and Mac with M1 Apple Silicon CPUs We're aware of a series of incompatibilities between the Android NDK and Macs on M1 CPUs ([here](https://github.com/android/ndk/issues/1299) and [here](https://github.com/android/ndk/issues/1410)). -As you need to enable the NDK when building from source, you might face problems during your build. +As the New Architectecture relies on the NDK, you might face problems during your build. -The workaround at this stage is [suggested here](https://github.com/android/ndk/issues/1299). -As newer version of the Android SDK/NDK are released, we will update the documentation with the necessary steps. +React Native version 0.70 and 0.71 contains fixes for those build failures, and we invite you to update to those versions whenever possible. diff --git a/docs/the-new-architecture/pillars-fabric-components.md b/docs/the-new-architecture/pillars-fabric-components.md index 577a38d6f90..7ea5a84c14a 100644 --- a/docs/the-new-architecture/pillars-fabric-components.md +++ b/docs/the-new-architecture/pillars-fabric-components.md @@ -17,7 +17,7 @@ A Fabric Native Component is a Native Component rendered on the screen using the A Fabric Native Component is created starting from a **JavaScript specification**. Then [**Codegen**](./pillars-codegen) creates some C++ scaffolding code to connect the component-specific logic (for example, accessing some native platform capability) to the rest of the React Native infrastructure. The C++ code is the same for all the platforms. Once the component is properly connected with the scaffolding code, it is ready to be imported and used by an app. -The following section guides you through the creation of a Fabric Native Component, step-by-step, targeting React Native 0.70.0. +The following section guides you through the creation of a Fabric Native Component, step-by-step, targeting the latest version of React Native. :::caution Fabric Native Components only works with the **New Architecture** enabled. @@ -215,13 +215,12 @@ The first part of the file prepares some variables that we use throughout the fi All the requirements for the New Architecture have been encapsulated in the [`install_modules_dependencies`](https://github.com/facebook/react-native/blob/82e9c6ad611f1fb816de056ff031716f8cb24b4e/scripts/react_native_pods.rb#L145). It takes care of installing the proper dependencies based on which architecture is currently enabled. It also automatically installs the `React-Core` dependency in the old architecture. -### Android: `build.gradle`, `AndroidManifest.xml`, a `ReactPackage` class +### Android: `build.gradle` and the `ReactPackage` class -To prepare Android to run **Codegen** you have to create three files: +To prepare Android to run **Codegen** you have to: -1. The `build.gradle` with the **Codegen** configuration -1. The `AndroidManifest.xml` file -1. A Java/Kotlin class that implements the `ReactPackage` interface. +1. Update the `build.gradle` file. +2. Create a Java/Kotlin class that implements the `ReactPackage` interface. At the end of these steps, the `android` folder should look like this: @@ -230,7 +229,6 @@ android ├── build.gradle └── src └── main - ├── AndroidManifest.xml └── java └── com └── rtncenteredtext @@ -251,7 +249,7 @@ buildscript { gradlePluginPortal() } dependencies { - classpath("com.android.tools.build:gradle:7.1.1") + classpath("com.android.tools.build:gradle:7.3.1") } } @@ -259,44 +257,29 @@ apply plugin: 'com.android.library' apply plugin: 'com.facebook.react' android { - compileSdkVersion safeExtGet('compileSdkVersion', 31) + compileSdkVersion safeExtGet('compileSdkVersion', 33) + namespace "com.rtncenteredtext" defaultConfig { minSdkVersion safeExtGet('minSdkVersion', 21) - targetSdkVersion safeExtGet('targetSdkVersion', 31) + targetSdkVersion safeExtGet('targetSdkVersion', 33) buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", "true") } } repositories { - maven { - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - url "$projectDir/../node_modules/react-native/android" - } mavenCentral() google() } dependencies { - implementation 'com.facebook.react:react-native:+' + implementation 'com.facebook.react:react-native' } ``` -#### The `AndroidManifest.xml` - -Second, create an `android/src/main` folder. Inside that folder, create a `AndroidManifest.xml` file, with the following code: - -```xml title="AndroidManifest.xml" - - -``` - -This is a small manifest file that defines the package for your module. - #### The `ReactPackage` class -Finally, you need a class that implements the `ReactPackage` interface. To run the **Codegen** process, you don't have to completely implement the Package class: an empty implementation is enough for the app to pick up the module as a proper React Native dependency and to try and generate the scaffolding code. +Then, you need a class that implements the `ReactPackage` interface. To run the **Codegen** process, you don't have to completely implement the Package class: an empty implementation is enough for the app to pick up the module as a proper React Native dependency and to try and generate the scaffolding code. Create an `android/src/main/java/com/rtncenteredtext` folder and, inside that folder, create a `CenteredTextPackage.java` file. @@ -660,7 +643,6 @@ android ├── build.gradle └── src └── main - ├── AndroidManifest.xml └── java └── com └── rtncenteredtext diff --git a/docs/the-new-architecture/pillars-turbomodule.md b/docs/the-new-architecture/pillars-turbomodule.md index 43688891768..ae86d282696 100644 --- a/docs/the-new-architecture/pillars-turbomodule.md +++ b/docs/the-new-architecture/pillars-turbomodule.md @@ -19,7 +19,7 @@ Turbo Native Modules are the next iteration on Native Modules that provide a few - Lazy loading of modules, allowing for faster app startup - The use of JSI, a JavaScript interface for native code, allows for more efficient communication between native and JavaScript code than the bridge -This guide will show you how to create a basic Turbo Native Module compatible with React Native 0.70.0. +This guide will show you how to create a basic Turbo Native Module compatible with the latest version of React Native. :::caution Turbo Native Modules only work with the **New Architecture** enabled. @@ -207,13 +207,12 @@ The first part of the file prepares some variables that we use throughout the fi All the requirements for the New Architecture have been encapsulated in the [`install_modules_dependencies`](https://github.com/facebook/react-native/blob/82e9c6ad611f1fb816de056ff031716f8cb24b4e/scripts/react_native_pods.rb#L145). It takes care of installing the proper dependencies based on which architecture is currently enabled. It also automatically installs the `React-Core` dependency in the old architecture. -### Android: `build.gradle`, `AndroidManifest.xml`, a `ReactPackage` class +### Android: `build.gradle` and `ReactPackage` class -To prepare Android to run **Codegen** you have to create three files: +To prepare Android to run **Codegen** you have to: -1. The `build.gradle` with the **Codegen** configuration -1. The `AndroidManifest.xml` file -1. A Java/Kotlin class that implements the `ReactPackage` interface +1. Update the `build.gradle` file. +2. A Java/Kotlin class that implements the `ReactPackage` interface At the end of these steps, the `android` folder should look like this: @@ -222,7 +221,6 @@ android ├── build.gradle └── src └── main - ├── AndroidManifest.xml └── java └── com └── rtncalculator @@ -243,7 +241,7 @@ buildscript { gradlePluginPortal() } dependencies { - classpath("com.android.tools.build:gradle:7.1.1") + classpath("com.android.tools.build:gradle:7.3.1") } } @@ -251,38 +249,23 @@ apply plugin: 'com.android.library' apply plugin: 'com.facebook.react' android { - compileSdkVersion safeExtGet('compileSdkVersion', 31) + compileSdkVersion safeExtGet('compileSdkVersion', 33) + namespace "com.rtncalculator" } repositories { - maven { - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - url "$projectDir/../node_modules/react-native/android" - } mavenCentral() google() } dependencies { - implementation 'com.facebook.react:react-native:+' + implementation 'com.facebook.react:react-native' } ``` -#### The `AndroidManifest.xml` - -Second, create an `android/src/main` folder. Inside that folder, create a `AndroidManifest.xml` file, with the following code: - -```xml title="AndroidManifest.xml" - - -``` - -This is a small manifest file that defines the package for your module. - #### The `ReactPackage` class -Finally, you need a class that extends the `TurboReactPackage` interface. To run the **Codegen** process, you don't have to completely implement the package class: an empty implementation is enough for the app to pick up the module as a proper React Native dependency and to try and generate the scaffolding code. +Then, you need a class that extends the `TurboReactPackage` interface. To run the **Codegen** process, you don't have to completely implement the package class: an empty implementation is enough for the app to pick up the module as a proper React Native dependency and to try and generate the scaffolding code. Create an `android/src/main/java/com/rtncalculator` folder and, inside that folder, create a `CalculatorPackage.java` file. @@ -536,7 +519,6 @@ android ├── build.gradle └── src └── main - ├── AndroidManifest.xml └── java └── com └── rtncalculator @@ -723,7 +705,6 @@ TurboModulesGuide │ ├── build.gradle │ └── src │ └── main - │ ├── AndroidManifest.xml │ └── java │ └── com │ └── rtncalculator