React 0.68+ Turbo Module starter using codegen with typescript for Objective-C and Java/Kotlin with C++ shared library. 🚀🚀🚀
- React Native 0.68+
- Upgraded react-native-create-library module to TurboModule
- Codegen with typescript
- Objective-C using JSI without the bridge
- Java/Kotlin using JSI without the bridge
- Shared C++ TurboModule
- Array/Dictionaries/Promises usage
- Native usage (battery level)
- M1 e2e Compilation of RN New Architecture
- This module doesn't offer backward compatibility. You will only be able to use it with the new architecture enabled.
- The shared C++ library requires JNI bindings on Android, and converting types on iOS from C++ to Objective-C.
- We didn't find an easy way to incorporate Swift instead of Objective-C (it's not as easy to call C++ code from Swift).
- We pin CMake version to support M1 machines. We also used CMake to compile the shared C++ library because it's the recommended tech (in oppose to ndk-build).
- In the
.podspec
file, the version of folly has to be exactly the same as the react-native's version - In case you are using an M1 machine, you will need to add the following to your local.properties file to build on Android (temporary workaround as mentioned here):
ndk.dir=/Users/{USER}/Library/Android/sdk/ndk/24.0.8215888
yarn bootstrap
yarn ios
yarn android
- Open
src/NativeTurboStarter.ts
- Add your function definition inside the Spec
- Open
src/index.ts
and export your new function via a wrapper - Call your new function from
App.tsx
to test that it works
- Run
RCT_NEW_ARCH_ENABLED=1 pod install
inexample/ios
folder - You can run
xed ios
to open to workspace, and on the left side-bar navigate toPods -> Development Pods -> react-native-turbo-starter -> ios -> TurboStarter.mm
and next to the@implementation
XCode will offer to complete the missing protocol for you - Alternatively, you can open
TurboStarter.mm
and implement the new function by yourself. - We're done! You can find the generated code in this path:
example/ios/build/generated/ios/TurboStarter
- run
./gradlew generateCodegenArtifactsFromSchema
in example/android - You can open Android Studio and access
android/src/main/java/com/reactnativeturbostarter/TurboStarterModule.kt
and let android studio complete the missing new function for you - Alternatively, you can open
TurboStarterModule.kt
and implement it by yourself - We're done! You can find the generated code in this path:
android/build/generated/source/codegen
Now you can re-run the example project and watch as your code runs with JSI!
Follow the steps above, but consider the following:
- Declare your C++ function here:
cpp/react-native-turbo-starter.h
- Implement your C++ function here:
cpp/react-native-turbo-starter.cpp
- In TurboStarter.mm, implement the function from the Spec, and you will be able to use it as a wrapper for calling the C++ code.
- You will need to convert the types when returning the function like so
- (NSNumber *) turboMultiply:(double)num1 num2:(double)num2{
double res = turbostarter::multiply(num1, num2);
return [NSNumber numberWithDouble:res];
}
- In
TurboStarterModule.kt
you will need to declare your native JNI function
private external fun nativeMultiply(num1: Double, num2: Double): Double
- Then you will be able to create a wrapper that calls the C++ code
override fun turboMultiply(num1: Double, num2: Double): Double {
return nativeMultiply(num1, num2)
}
- In
android/src/main/jni/cpp-adapter.cpp
you will need to add the JNI function that wraps around the C++ function
extern "C" JNIEXPORT jdouble JNICALL
Java_com_reactnativeturbostarter_TurboStarterModule_nativeMultiply(JNIEnv *env, jclass type, jdouble num1, jdouble num2)
{
return turbostarter::multiply(num1, num2);
}
- Create the repo using react-native-create-library (https://github.com/talknagish/react-native-turbo-starter/commit/f755c6ec6aa653d46a92474592de552cb3ba3f6c)
- Upgrade the library to react-native 0.68 (talknagish#1)
- Upgrade the example to react-native 0.68 and call 1 turbo module function (talknagish#2)
- Expend the Spec and call complex types (talknagish#3)
- Call native code (talknagish#4)
- Add the shared C++ library (talknagish#5)
- Full refresh (cmd + R) on Android crashes the application because of an issue in shadowTreeRegistry.cpp (didn't find a respective issue in their repo)
- When building for Android codegen doesn't always generate the new spec, so sometimes you have to delete the build folders until we find a better solution
It's all nice but how do we know this is actually not using the bridge anymore? To see that we enabled JSI correctly, you can log out everything that is passing through the bridge and see that it's now clean (besides some data from metro-bundler)
in App.tsx
-
Add
import MessageQueue from 'react-native/Libraries/BatchedBridge/MessageQueue.js';
const spyFunction = (msg) => {
console.log(msg);
};
- Call
MessageQueue.spy(spyFunction);
- clone
react-native-turbo-starter
- cd
react-native-turbo-starter
rm -rf .git
- rename all files containing
starter
word (script in the future) git init
git remote add origin <new repo url>
git add .
git commit -m "Initial Commit"
git push -u origin main
MIT