Skip to content
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

Support for bridgeless NativeModule in New Architecture #194

Merged
merged 8 commits into from
Feb 7, 2025

Conversation

evan-masseau
Copy link
Contributor

@evan-masseau evan-masseau commented Jan 30, 2025

Description

This aims to add android support for the New Architecture by narrowing our current implementation to be exclusively a NativeModule that can run in bridgeless mode in new arch apps. I believe we had already stripped turbo module codegen from iOS in an earlier issue when we took out some podspec flags that were causing issues for customers.

This will be a stepping stone toward proper TurboModule support. Since that migration may take longer, this can unblock folks who need new arch ASAP.

Check List

  • Are you changing anything with the public API? -- NO
  • Are your changes backwards compatible with previous SDK Versions? -- So far yes, pending full regresssion testing

Changelog / Code Overview

In our initial commit we selected a template intended to support Native and Turbo Modules. Since we didn't fully implement TurboModules for version 1.0, the migration to New Architecture in RN 0.76.0 uncovered an issue for us: codegen was still running and erroring out on Android builds. To remedy this, I referenced the latest NativeModule project template to ensure we are up to date with best practices for making a NativeModule available on the New Architecture and upgraded the example app to 0.77.0 to catch up to the now-default architecture for new apps. Since we're still a Native Module, old arch support should be unaffected.

Test Plan

Until I publish an alpha to npm, this version can be installed with:
npm install [email protected]:klaviyo/klaviyo-react-native-sdk.git#ecm/bridgeless

Test plans:

  • Github CI covers example app compiling and building on each platform, and will now be defaulting to new arch.
    • It would be great if the CI could run against new and old arch, gotta look at the build scripts.
  • Test against the bug repo provided in issue Compilation error for Android on latest React Native 0.76 with new architecture enabled #185 for compilation
  • Manual tests of example app to confirm all SDK constants, setters, getters etc are bridging correctly (in progress)
  • Migrate internal test app to new architecture -- note this requires more package updates since we rely on more 3rd party libs for that app (in progress)

Related Issues/Tickets

#185

@@ -1,9 +1,57 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
#!/bin/sh
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was from the new project template, it moves our git hooks to lefthook.yml. I don't have a strong opinion, but just figured I'd adopt it while we're updating

@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Kenny Tsui
Copyright (c) 2025 Klaviyo
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Autogenerated by the template, no offense Kenny <3

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lolll

@@ -79,20 +83,6 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These gradle changes were necessary yet not sufficient for removing the turbomodule code gen from our project for now. When we do add TM support, they'll have to come back

android/gradle/wrapper/gradle-wrapper.properties Outdated Show resolved Hide resolved
@@ -14,6 +14,11 @@ buildscript {
}
}

def reactNativeArchitectures() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just came from the template

# commands:
# commitlint:
# run: npx commitlint --edit
pre-commit:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our pre-commit logic lives here now, still installed via husky tho

"jest": {
"preset": "react-native",
"modulePathIgnorePatterns": [
"<rootDir>/example/node_modules",
"<rootDir>/lib/"
]
},
"commitlint": {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we weren't using this, and it enforces a rather annoying commit message format that I don't expect our devs to follow, for the most part because we typically squash merge and format commit messages at that time.

// @ts-expect-error
const isTurboModuleEnabled = global.__turboModuleProxy != null;

const KlaviyoReactNativeSdkModule = isTurboModuleEnabled
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was supposed to be the basis of supporting NativeModules or TurboModules in the same lib. We'll probably have to revive this in the next phase so that we can maintain NM support when we add TM.

@@ -2,6 +2,7 @@
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build:android": {
"env": ["ORG_GRADLE_PROJECT_newArchEnabled"],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

turbo build != turbo modules, but I did copy over this default env variable for new arch

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is turbo build? 😮‍💨

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turborepo is a high-performance build system for monorepos, allowing you to manage multiple packages within a single repository efficiently. It optimizes build processes by caching and parallelizing tasks, resulting in faster development builds and improved performance.

I guess there's only so many adjectives in the english language lol. This was something that really boosted our CI performance especially iOS (but also caused those caching woes when we first added the GH actions)

@@ -1,5 +1,3 @@
import { TurboModuleRegistry } from 'react-native';
Copy link
Contributor Author

@evan-masseau evan-masseau Jan 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renaming this file was probably the least obvious yet most important change. Evidently the Native* prefix is detected by codegen. I would get a different error relating to CMake trying to build for libs that the package does not actually provide.
I had expected that renaming this, in combination with the build.gradle changes above, should have fixed our new arch code gen issues... but didn't. That's why I suspect there might have been an additional underlying bug in the RN/gradle libs but didn't have the time/bandwitdth to track it down myself. Besides which, this was a good time to update to latest RN version anyways so it wasn't really worth the effort.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat find!

Comment on lines -20 to -21
android.enableJetifier=true
android.useAndroidX=true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these defaulted to true now? or incompatible with new arch

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just noticing this as well. I'm not sure about jetifier, but we use androidX so that probably needs to come back

Copy link
Contributor Author

@evan-masseau evan-masseau Jan 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking back in git, it appears I added them pretty early on, but I'm not clear why. They weren't part of the original template, nor are they in the latest one. And I'm not sure why we'd need them, since the SDK's android files do not make use of androidx at all.
The example app does have useAndroidx=true which makes sense because it has androidx dependency for the activities and notifications and such.
So I'm thinking this is safe to remove.

Copy link
Collaborator

@ajaysubra ajaysubra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM some minor comments/questions.

if [ -f "package-lock.json" ];
then echo "package-lock.json is not allowed";
exit 1;
if [ "$LEFTHOOK" = "0" ]; then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fast. It is written in Go. Can run commands in parallel.
Okay!

ndkVersion = "25.1.8937393"
kotlinVersion = "1.8.0"
buildToolsVersion = "35.0.0"
minSdkVersion = 24
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so on native we support 23 but for RN it's only 24 onwards? NBD but checking.

@@ -21,8 +21,6 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any implication of removing this?

@@ -546,7 +546,7 @@
"$(inherited)",
);
INFOPLIST_FILE = KlaviyoReactNativeSdkExampleTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think same question as android, if someone where to update to these RN version they are letting go of lower iOS versions so it's not really us who is responsible for the higher min deployment target?

example/package.json Show resolved Hide resolved
package.json Show resolved Hide resolved
@@ -1,5 +1,3 @@
import { TurboModuleRegistry } from 'react-native';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat find!

@@ -2,6 +2,7 @@
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build:android": {
"env": ["ORG_GRADLE_PROJECT_newArchEnabled"],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is turbo build? 😮‍💨

@@ -1,3 +1,3 @@
module.exports = {
presets: ['module:@react-native/babel-preset'],
presets: ['module:react-native-builder-bob/babel-preset'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary? Just confused on its relevance to this change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were quite a number of changes irrelevant to the turbomodules / new arch fix itself, that just came along with updating to the latest RN Native Module library template. I'm not certain about this one, but agree it'd be good to read up just to stay up to date with RN practices.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://callstack.github.io/react-native-builder-bob/faq

react-native-builder-bob wraps tools such as babel and typescript to simplify these common tasks across multiple projects. While it can be used for any library, it's primarily tailored to React Native projects to minimize the configuration required.

yup so just some build tools moving around.

@ashiu95 ashiu95 merged commit e81662f into master Feb 7, 2025
9 checks passed
@ashiu95 ashiu95 deleted the ecm/bridgeless branch February 7, 2025 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Compilation error for Android on latest React Native 0.76 with new architecture enabled
6 participants