How to use offline bundle on android for react native project?
How to use offline bundle on android?
I didn`t see the document about use offline bundle on android.
I tried to uncomment the code in build.gradle.
project.ext.react = [
// the name of the generated asset file containing your JS bundle
bundleAssetName: "index.android.bundle",
// the entry file for bundle generation
entryFile: "index.android.js",
// whether to bundle JS and assets in debug mode
bundleInDebug: false,
// whether to bundle JS and assets in release mode
bundleInRelease: true,
// the root of your project, i.e. where "package.json" lives
root: "../../",
// where to put the JS bundle asset in debug mode
jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
// where to put the JS bundle asset in release mode
jsBundleDirRelease: "$buildDir/intermediates/assets/release",
// where to put drawable resources / React Native assets, e.g. the ones you use via
// require('./image.png')), in debug mode
resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
// where to put drawable resources / React Native assets, e.g. the ones you use via
// require('./image.png')), in release mode
resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
// by default the gradle tasks are skipped if none of the JS files or assets change; this means
// that we don't look at files in android/ or ios/ to determine whether the tasks are up to
// date; if you have any other folders that you want to ignore for performance reasons (gradle
// indexes the entire tree), add them here. Alternatively, if you have JS files in android/
// for example, you might want to remove it from here.
inputExcludes: ["android/**", "ios/**"]
]
but it didn`t work.It still fetch the JS bundle from the server.
Is there something I missed?
Solution 1:
For offline bunduling of JS into android, first start the server in respective project path:
- when server start, open next terminal with same path as project path
-
copy and paste this command: Before you copy and paste command in command propmt, make assets folder in project respective path
as:
android/app/src/main/assetspaste this command in command prompt and run:
react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
- Then in assets folder there will appear file as index.android.bundle
- Finally, run command: react-native run-android(while building new offline apk you need not to start server, your offline js file will help you to build apk file.)
- Final, apk now build is ready for running in different devices(run apk from app/src/build/debug.apk).
- Sometimes newly made apk will run without showing images, If application runs without image , then copy and paste the specific image resource folder into android/app/src/main/assets/(image source folder)
- Again rerun application and thus build apk is ready for running.
Solution 2:
You can read the source code of react.gradle
,then you will know how to do the offline bundle.
In react.gradle
, it creates offline bundle gradle task for each build variant, and make it execute before gradle process resources, but it enables the bundle task in some special conditions, the code is:
enabled config."bundleIn${targetName}" ||
config."bundleIn${buildTypeName.capitalize()}" ?:
targetName.toLowerCase().contains("release")
while the config
object is the react
object actually as its definition is
def config = project.hasProperty("react") ? project.react : [];
and the targetName
definition is def targetName = "${productFlavorName.capitalize()}${buildTypeName.capitalize()}"
So if we define a proper react
property in app\build.gradle
, we can enable the offline bundle task.
For example, if we want to enable the offline bundle in release
build type but not in debug
build type ,we can define the react
as:
ext.react = [
bundleInDebug : false,
bundleInRelease : true
]
then execute gradle assembleRelease
in command line, gradle will execute the bundle task and the js bundle will be included in final apk.
Now in your question, you have defined the proper react
object, but you don't mention which build type you have ran. Only execute gradle assembleRelease
can do the bundle job, maybe you executed gradle assembleDebug
so it does not make any sense.
And there is still another problem I need to say(Also see in issue7258). If you enabled the bundle task for release build type and run app from android studio, gradle don't execute bundleReleaseJsAndAssets
, because android studio enable the feature Configure on demand
(it's in File | Settings | Build, Execution, Deployment | Compiler) by default for speeding up build, and in react.gradle
the bundle task is add to project when all project are configured(or called evaluated) as the main code is in gradle.projectsEvaluated{}
block.
Configuration on demand mode attempts to configure only projects that are relevant for requested tasks, i.e. it only executes the build.gradle file of projects that are participating in the build.
For some unclear reasons, any task define in gradle.projectsEvaluated{}
block doesn't executed when enable the Configure on demand
feature. To make it executable, disable the Configure on demand
feature in android studio settings, or change gradle.projectsEvaluated{}
to afterEvaluate{}
.
If you run gradle assembleRelease
in command line tool, everything is ok because Configure on demand
is disabled by default.
Solution 3:
You do not have to uncomment anything in your gradle.build file. It is there for reference and you can overwrite any of the values which are there as defaults if you need to.
The problem is that Android Studio is not running the task that is responsible for generating the bundle.
To fix that in Android Studio go to Preferences > Build, Execution, Deployment > Build Tools > Compiler
and uncheck "Configure on demand"
.
Now, any variant which you mark as requiring bundle, will have the bundle generated automatically.
By default, debug variant does not get the bundle generated: bundleInDebug : false
You can change that like this. Here I also provided example how to change the default location of the entry point and default name of the bundle.
project.ext.react = [
bundleAssetName: "index.myapp.bundle",
entryFile: "js/index.myapp.js",
bundleInDebug: true
]
Once you make these adjustments, you may still tun into issues building because Studio does not recognise paths from your shell profiles, so i may not find the path to node.
I posted a solution to that issue here
This is a stable and robust solution. You do not have to do anything manually once you make these changes in your env. Bundle will be built automatically as you press the buttons in your IDE, granted you select proper build variants (that is also in IDE on the LHS bar of the Studio window towards the bottom).
Solution 4:
When building an unsigned apk from react native project through create-react-native-app which does not have index.android.js and index.ios.js .so first of all you have to check that wheter index.js file is there in your project .if it is not available then create a new file index.js and write this code there
import { AppRegistry } from "react-native";
import App from "./App";
AppRegistry.registerComponent("VOS", () => App);
after this eject the project and then run this command
react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
and then react-native run-android
so it will build an apk for you.