Skip to content

fix(android): make prebuild work on Expo SDK 56 and 57 - #28

Merged
GSTJ merged 3 commits into
masterfrom
fix/expo-sdk-57-prebuild
Jul 27, 2026
Merged

fix(android): make prebuild work on Expo SDK 56 and 57#28
GSTJ merged 3 commits into
masterfrom
fix/expo-sdk-57-prebuild

Conversation

@GSTJ

@GSTJ GSTJ commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Closes #26.

npx expo prebuild throws on Expo SDK 57 and SDK 56. Both broken mods anchor on strings the template stopped emitting.

app/build.gradle

applyImplementation looked for one of four apply from: lines and threw when it found none. RN 0.75 folded autolinking into autolinkLibrariesWithApp() inside the react { } block, so on SDK 56+ there's no apply from: in the file at all.

codepush.gradle reads the react extension and iterates android.buildTypes while it's being applied, so it has to run after both blocks are configured. The end of the app module's build.gradle is where that holds on every template shape, and it's also where the RN 0.71-0.73 anchor happened to sit, so SDK 49 and 50 land in the same spot they always did. The mod appends there now.

It also throws a readable error if app/build.gradle is Kotlin DSL, where apply from: wouldn't parse.

MainApplication

Flagged in the issue as the next one waiting, and prebuild hits it as soon as the gradle mod stops throwing.

SDK 56 dropped ReactNativeHost from the template, so there's no getJSBundleFile() to override. The host comes from ExpoReactHostFactory.getDefaultReactHost, which takes jsBundleFilePath as an argument. The mod passes CodePush.getJSBundleFile() there, as the last argument: Kotlin evaluates arguments in source order, and that call throws CodePushNotInitializedException until PackageList(this).packages has built the CodePush instance. Getting to the closing parenthesis means matching it, because the argument list contains a commented-out add(MyReactNativePackage()) that a plain search walks straight into.

import expo.modules.ReactNativeHostWrapper is gone too, so the CodePush import now goes below the last import in the file. The ReactNativeHost paths stay for SDK 49-55, minus the getJSMainModuleName(): String = ".expo/.virtual-metro-entry" anchor, which only ever matched SDK 50's exact string.

Proof

Blank create-expo-app on expo@57.0.8 / react-native@0.86.0, plugin wired into app.json, npx expo prebuild --platform android --clean.

Before, v1.0.11 from npm:

prebuild failing on SDK 57 with v1.0.11

After, this branch packed and installed into the same app:

prebuild succeeding on SDK 57, with the generated gradle and Kotlin

Same branch against an expo@50.0.21 / react-native@0.73.6 app, which is what the README was tested on:

prebuild on SDK 50 producing the same output as before

Running prebuild twice without --clean leaves one apply from:, one getJSBundleFile, one import and one include ':react-native-code-push'.

Local checks:

lint, format, typecheck, 31 tests, build and pack all passing

Tests run against both templates verbatim, kept in src/android/__tests__/templates.ts, plus the parenthesis matcher on comments, escaped strings, Kotlin raw strings and nesting. 31 tests, up from 5.

Out of scope

I stopped at prebuild. No Gradle build ran, so codepush.gradle applying cleanly under AGP on RN 0.86 is unverified, and react-native-code-push@9.0.1 was published against RN 0.72 and hasn't moved since the repo was archived. If the runtime turns out to be broken under bridgeless, that belongs in the SDK's tracker and needs its own issue here.

iOS is still broken on SDK 52+ for the same class of reason: withIosAppDelegateDependency looks for #import "AppDelegate.h" and the template is Swift now. Nothing throws, so Info.plist gets written and the bundle URL never gets redirected. Separate fix, filing it.

https://claude.ai/code/session_01QsVEsfkynXpJWK4t33exG9

GSTJ added 3 commits July 27, 2026 20:20
`applyImplementation` searched app/build.gradle for one of four
`apply from:` lines and threw when it found none. React Native 0.75
folded autolinking into `autolinkLibrariesWithApp()` inside the
`react { }` block, so by Expo SDK 56 the file has no `apply from:` left
and prebuild died with "Cannot find a suitable place to insert the
CodePush buildscript dependency".

Those anchors were never the requirement. `codepush.gradle` reads the
`react` extension and iterates `android.buildTypes` as it is applied, so
it has to run after both blocks are configured, and the end of the file
is where that holds on every template. It also happens to be where the
old anchor sat in RN 0.71-0.73, so SDK 49 and 50 land in the same place
they always did.

Closes #26

Claude-Session: https://claude.ai/code/session_01QsVEsfkynXpJWK4t33exG9
Expo SDK 56 dropped `ReactNativeHost` from the template, so there is no
`getJSBundleFile()` left to override. `MainApplication` now builds a
`ReactHost` through `ExpoReactHostFactory.getDefaultReactHost`, which
takes `jsBundleFilePath` as an argument instead.

The mod passes `CodePush.getJSBundleFile()` there. It has to be the last
argument: Kotlin evaluates arguments in source order, and that call
throws until `PackageList(this).packages` has constructed the CodePush
instance. Finding the closing parenthesis means matching it rather than
searching for one, since the template's argument list contains a
commented-out `add(MyReactNativePackage())`.

The import anchor moves with it. It used to be
`import expo.modules.ReactNativeHostWrapper`, which SDK 56 also stopped
emitting, and is now the end of the import block.

The `ReactNativeHost` paths stay for SDK 49 through 55, minus the
`getJSMainModuleName` anchor that only ever matched SDK 50's exact
string.

Claude-Session: https://claude.ai/code/session_01QsVEsfkynXpJWK4t33exG9
Android is covered on SDK 50 and 57. iOS writes Info.plist but leaves
the Swift AppDelegate that SDK 52 and up generate untouched, since the
mod still looks for the Objective-C `#import "AppDelegate.h"`.

Claude-Session: https://claude.ai/code/session_01QsVEsfkynXpJWK4t33exG9
@GSTJ
GSTJ merged commit 641ad2c into master Jul 27, 2026
4 checks passed
@GSTJ
GSTJ deleted the fix/expo-sdk-57-prebuild branch July 27, 2026 23:33
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.

Prebuild throws on Expo SDK 57: no apply from: anchor in app/build.gradle

1 participant