From 13b9cecb5fcea377a2b756f1a8040b7832d35b73 Mon Sep 17 00:00:00 2001 From: Radoslaw Nowacki Date: Tue, 29 Sep 2026 13:05:19 +0200 Subject: [PATCH] fix(bgp): publish embedded community libraries' dependencies on Expo On Expo projects only Expo modules were scanned for transitive dependencies. Community libraries (react-native-screens, lottie-react-native, Brownie...) were packed into the AAR but their dependencies were left off the POM, so host apps built fine and then crashed with NoClassDefFoundError at runtime. Run the embedded-library discoverer on Expo too; the existing hard-exclude filter keeps Expo coordinates out of the POM. ExpoApp57 now renders lottie-react-native, whose Android dependency the AndroidApp host doesn't otherwise have, so the existing E2E tests fail if it is missing from the POM again. --- .changeset/quiet-trains-track.md | 5 +++++ apps/ExpoApp57/package.json | 1 + apps/ExpoApp57/src/app/index.tsx | 7 +++++++ docs/docs/docs/guides/troubleshooting.mdx | 2 +- .../brownfield/plugin/RNBrownfieldPlugin.kt | 8 ++++---- .../react/brownfield/utils/Extension.kt | 4 ++-- yarn.lock | 18 ++++++++++++++++++ 7 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 .changeset/quiet-trains-track.md diff --git a/.changeset/quiet-trains-track.md b/.changeset/quiet-trains-track.md new file mode 100644 index 00000000..bdd48d87 --- /dev/null +++ b/.changeset/quiet-trains-track.md @@ -0,0 +1,5 @@ +--- +'@callstack/react-native-brownfield': patch +--- + +fix: publish dependencies of community libraries (e.g. react-native-screens, lottie-react-native) embedded in Expo brownfield AARs; the published POM now lists them, previously host apps could crash with NoClassDefFoundError diff --git a/apps/ExpoApp57/package.json b/apps/ExpoApp57/package.json index a9fb3863..cdcae0a6 100644 --- a/apps/ExpoApp57/package.json +++ b/apps/ExpoApp57/package.json @@ -21,6 +21,7 @@ "expo-system-ui": "~57.0.0", "expo-updates": "^57.0.6", "expo-web-browser": "~57.0.0", + "lottie-react-native": "~7.3.8", "react": "19.2.3", "react-dom": "19.2.3", "react-native": "0.86.0", diff --git a/apps/ExpoApp57/src/app/index.tsx b/apps/ExpoApp57/src/app/index.tsx index d35250db..6c573403 100644 --- a/apps/ExpoApp57/src/app/index.tsx +++ b/apps/ExpoApp57/src/app/index.tsx @@ -1,4 +1,5 @@ import * as Device from 'expo-device'; +import LottieView from 'lottie-react-native'; import { Button, Platform, StyleSheet } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { brownfieldE2ETestIds } from '@callstack/brownfield-example-shared-tests/e2eTestIds'; @@ -37,6 +38,12 @@ export default function HomeScreen() { style={styles.container} > + {/* Community library with its own Android dependency: the host crashes if it's missing from the POM. */} + + { } transitiveDeps.addAll(expoTransitiveDeps) } - // Never on Expo: the path above already covers every embedded module there, and the RNC - // discoverer doesn't filter by the Expo blacklist, so running both leaks Expo coordinates. - if (!isExpoProject && extension.experimentalIncludeTransitiveDependencies) { + // Also on Expo: the path above only covers Expo modules, not community libraries. + if (extension.experimentalIncludeTransitiveDependencies) { val rncDiscovery = RncTransitiveDependencyDiscoverer(project).discover(artifacts) Logging.log( "Merged ${rncDiscovery.dependencies.size} transitive dependencies discovered by the RNC discoverer", @@ -143,7 +142,8 @@ class RNBrownfieldPlugin : Plugin { // (replacing a stale entry) and so must not be dropped here. val hardExcludePredicate: (String, String) -> Boolean = { groupId, artifactId -> (expoPublishingHelper?.shouldExcludeDependency(groupId, artifactId) ?: (groupId == project.rootProject.name)) || - artifacts.any { it.moduleGroup == groupId && it.moduleName == artifactId } + artifacts.any { it.moduleGroup == groupId && it.moduleName == artifactId } || + expoProjects.any { it.publication?.groupId == groupId && it.publication?.artifactId == artifactId } } dropHardExcludedDependencies(transitiveDeps, hardExcludePredicate) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt index bb9c79da..4d55376a 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt @@ -58,8 +58,8 @@ open class Extension { * Whether to publish embedded native modules' third-party dependencies into the generated POM * and Gradle Module Metadata, so consuming apps resolve them instead of declaring them by hand. * - * Experimental; behavior may still change. Applies to non-Expo (RNC CLI) projects only — Expo - * gets this unconditionally. Set to `false` to hand-declare them instead. + * Experimental; behavior may still change. On Expo projects, Expo modules' dependencies are + * published regardless; this covers the other native modules. Set to `false` to hand-declare them instead. * * Default is `true`. */ diff --git a/yarn.lock b/yarn.lock index 61002589..25082336 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1905,6 +1905,7 @@ __metadata: expo-system-ui: "npm:~57.0.0" expo-updates: "npm:^57.0.6" expo-web-browser: "npm:~57.0.0" + lottie-react-native: "npm:~7.3.8" react: "npm:19.2.3" react-dom: "npm:19.2.3" react-native: "npm:0.86.0" @@ -16152,6 +16153,23 @@ __metadata: languageName: node linkType: hard +"lottie-react-native@npm:~7.3.8": + version: 7.3.8 + resolution: "lottie-react-native@npm:7.3.8" + peerDependencies: + "@lottiefiles/dotlottie-react": ^0.13.5 + react: "*" + react-native: ">=0.46" + react-native-windows: ">=0.63.x" + peerDependenciesMeta: + "@lottiefiles/dotlottie-react": + optional: true + react-native-windows: + optional: true + checksum: 10/050154a675de4aeff10d629ca48743806818ebe4c79d041e0983ff278a59e2d59f4e88b559a6d681e49d7d82b253ad969909d9cde9a887bc22c8a2ebf05c2538 + languageName: node + linkType: hard + "lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": version: 10.4.3 resolution: "lru-cache@npm:10.4.3"