Within andorid/app/build.gradle
file, define staging
build type, set bundleInStaging
to true
and produce unsigned APK by running ./gradlew assembleStaging
There are many different suggestions on how to use react-native bundle
command to produce React Native JavaScript bundle together with other resources and put them to the correct place so that ./assembleDebug
can take them and create unsigned APK.
Some of them use android/app/src
as a target location which results in having those files in an inappropriate place and in source control with React Native default .gitignore
. But they end up in the APK because this is where native Android apps put their static assets.
The rest of the suggestions, including official React Native CLI docs, put them correctly to the android/app/build
folder. But most of them do not result in JavaScript bundle being part of the APK with the latest React Native version.
The answer lies in react.gradle
file within react-native repository, where official Gradle tasks for bundling and copying reside.
bundleDebugJsAndAssets
Gradle task puts it's output by default to android/app/build/generated
directory:
- JS bundle:
android/app/build/generated/assets/react/debug/index.android.bundle
- Resources:
android/app/build/generated/res/react/debug
While this is the target location for the resources, it is not yet the final location for the bundle. It won't be picked up from here and placed to the APK.
copyDebugBundledJs
Gradle task takes care of that and copies these files to multiple locations within android/app/build/intermediates
directory:
.../intermediates/merged_assets/debug/out/index.android.bundle
.../intermediates/merged_assets/debug/mergeDebugAssets/out/index.android.bundle
.../intermediates/assets/debug/index.android.bundle
So why there are so many people trying to mimic this behavior with react-native bundle
command? Because both bundleDebugJsAndAssets
and copyDebugBundledJs
are skipped by default when running assembleDebug
task. The answer lies in the comments within android/app/build.gradle
file:
The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets and bundleReleaseJsAndAssets). These basically call
react-native bundle
with the correct arguments during the Android build cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the bundle directly from the development server.
This behavior is determined by bundleInDebug
configuration option, that is set to false by default because of the reasons mentioned above.
So where lies the solution?
Simply set bundleIn${buildType}
to true. But not for the debug build type which is used in react-native run-android
command. Define a new build type that produces unsigned APK:
andorid/app/build.gradle
file:
...
project.ext.react = [
...
bundleInStaging: true,
devDisabledInStaging: true,
]
...
android {
buildTypes {
...
staging {
signingConfig signingConfigs.debug
matchingFallbacks = ['debug']
}
...
And simply run the assemble Gradle task from the android
directory:
./gradlew assembleStaging
Now, whatever changes there will be in the future with the bundle and resource locations, you can have a restful sleep because React Native official Gradle tasks take care of that for you.
Hi Abdullah,
The problem with the development menu I think comes from the usage of of the
debug
build type fallback. When you build the app, it's still in the debug configuration and because of that the developer menu is still enabled. I'm not sure how to overcome that, but I believe is certainly possible. You might find your answer in the react native codebase as I did with this article.BTW you should not use debug for this IMO. By setting
devDisabledInDebug
totrue
, you are saying that development server and everything that comes with it won't be available in debug mode. Which you need for development. I believe there is nothing wrong with introducing a new build type.Good luck!