How to reduce the size of an expo/react-native app on Android - react-native

I am developing a small dictionary app by using react native with expo.
As I am compiling to Apk file. The size goes up to 30mb and after having installed on a device, it goes to 80mb.
Is this normal?
Are there any ways to reduce the size of the app?
Thank you guys.

For android APK bundle using expo, you can use the following command:
expo build:android -t app-bundle
The size will be much smaller once you upload it to the play store.
This is relevant for React Native SDK 32 and earlier.

the expo is for development the app you should migrate to react-native for production
make a new react app "react-native init"
Copy the source files over from Expo project
Install all dependencies of the Expo project except Expo specific libraries.
Make necessary adjustments to app.json file
Download the signing key of your Android app from Expo using exp
fetch:android:keystore and set it up
This reduces your app dramatically you can also enable proguard and specific build for cpu architecture
buildTypes {
release {
debuggable false
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
for more info visit https://medium.com/#aswinmohanme/how-i-reduced-the-size-of-my-react-native-app-by-86-27be72bba640
using expo component
after you done and want publish with less size or just wan't to use a native library expo give you an option called ExpoKit this also can be used with already build with native code react projects
1-run command expo eject to add ExpoKit (choose the "ExpoKit" option)
(no need to do this if you have copied files manually or using native project)
2 -start expo packager with expo start.Leave this running and continue with the following steps.
3-
link library for android and ios, this command mostly do this react-native link, sometime this will not work and you should do it manually for this means visit expokit
PS: I didn't test this so if this not work inform me

Make following changes in build.gradle file located at:
./android/app/build.gradle
Remove x86 from abi filters.
splits {
abi {
reset()
enable true
universalApk false
include "armeabi-v7a", "x86"
}
}
Generate different APK's for different architecture
def enableSeparateBuildPerCPUArchitecture = true
Enable ProGuard :
def enableProguardInReleaseBuilds = true
Also set minifyEnabled true and shrinkResources true
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
Also, you can have different build types for development and release builds(depends on your user base)
buildTypes {
debug {
ndk {
abiFilters "armeabi-v7a", "x86"
}
....
}
release {
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
....
}
Also don't forget to remove the unused FONT Files

As of 2021, there is now a much easier option to reduce Android binary size, since ejecting/migrating to pure react-native, switching to bare workflow and building your own binaries locally requires a lot of work and study if you don't know how to do it already or don't have your environment and tools all set up.
In app.json, make the following changes:
"expo": {
...
"android": {
"enableDangerousExperimentalLeanBuilds": true
}
}
This alone should reduce app size in ~40-50% depending on your project.
There's a few things you should know about using this option, so you should read
https://github.com/expo/fyi/blob/master/managed-app-size.md. It's still WAY easier than ejecting.
on top of that, you should still use app bundles (.aab) to get another ~50% size reduction after uploading to the play store:
expo build:android -t app-bundle

the other way to reduce your app size without manually copy-paste your code in another repo. In app.json or app.config.js just set it enableDangerousExperimentalLeanBuilds to true, by doing this expo won't install the unnecessary node modules when you are running expo build:android -t app-bundle.
If you run into any crashes compare the native node modules which are installed before enabling enableDangerousExperimentalLeanBuilds and install only the required one. You can find the native node modules installed in the expo.io build artefacts.
here are some node module that come along with managed flow which you may not require
expo-ads-admob:8.3.0
expo-analytics-amplitude:8.3.1
expo-ads-facebook:8.4.0
expo-analytics-segment:9.0.0
unimodules-constants-interface:5.3.0
expo-app-auth:9.2.0
expo-apple-authentication:2.2.1
unimodules-app-loader:1.3.0
unimodules-font-interface:5.3.0
unimodules-image-loader-interface:5.3.0
unimodules-permissions-interface:5.3.0
expo-application:2.3.0
expo-av:8.6.0
expo-background-fetch:8.5.0
expo-task-manager:8.5.0
unimodules-task-manager-interface:5.3.0
expo-barcode-scanner:9.0.0
unimodules-barcode-scanner-interface:5.3.0
expo-battery:3.0.0
expo-blur:8.2.0
expo-brightness:8.3.0
expo-calendar:8.5.0
expo-camera:9.0.0
unimodules-camera-interface:5.3.0
unimodules-face-detector-interface:5.3.0
unimodules-file-system-interface:5.3.0
expo-cellular:2.3.0
expo-constants:9.2.0
expo-contacts:8.5.0
expo-crypto:8.3.0
expo-device:2.3.0
expo-document-picker:8.4.0
expo-error-recovery:1.3.0
expo-face-detector:8.3.0
expo-facebook:9.0.0
expo-file-system:9.2.0
expo-firebase-analytics:2.5.0
expo-firebase-core:1.2.0
expo-font:8.3.0
expo-gl:9.1.1
expo-gl-cpp:9.1.2
expo-gl-cpp-legacy:8.4.0
expo-google-sign-in:8.3.0
expo-haptics:8.3.0
expo-image-loader:1.2.0
expo-image-manipulator:8.3.0
expo-image-picker:9.1.1
expo-permissions:9.3.0
expo-in-app-purchases:9.0.0
expo-intent-launcher:8.3.0
expo-keep-awake:8.3.0
expo-linear-gradient:8.3.0
expo-local-authentication:9.3.0
expo-localization:9.0.0
expo-location:9.0.0
expo-mail-composer:8.4.0
expo-media-library:9.2.1
expo-module-template:8.4.0
expo-network:2.3.0
expo-notifications:0.7.2
expo-payments-stripe:8.3.0
expo-print:9.1.0
expo-screen-capture:1.1.1
expo-screen-orientation:2.0.0
expo-secure-store:9.2.0
expo-sensors:9.1.0
unimodules-sensors-interface:5.3.0
expo-sharing:8.4.1
expo-sms:8.3.1
expo-speech:8.4.0
expo-splash-screen:0.6.2
expo-sqlite:8.4.0
expo-store-review:2.2.0
expo-updates:0.3.3
expo-video-thumbnails:4.3.0
expo-web-browser:8.5.0

My suggestion will be for you to upgrade to EAS, with EAS your build size is reduced by more than 3/4, however, at this point, you have to pay $29 but I promise you it's worth it. An app I have been working on prompting into EAS reduced the bundle size from 80MB to 16MB😱. EAS also has EAS submit which enables you submit your app to the stores in a Flash

You can avoid copying the source code from the existing expo project to another project as suggested in this comment
If you use eas build (not expo build) you can try to set up enableProguardInReleaseBuilds param in app.json.
Example:
{
"expo": {
"plugins": [
[
"expo-build-properties",
{
"android": {
"enableProguardInReleaseBuilds": true,
}
}
]
]
}
}
Reference: https://docs.expo.dev/versions/latest/sdk/build-properties/#pluginconfigtypeandroid

Upgrade react-native to newer version, for different versions it is giving different size apk.
for 0.57 it was ≈12mb
for 0.59.3 it was ≈30mb
and for 0.59.9 it was ≈15mb
always try to use updated react-native version

There are basically two options for reducing size of apk file from 32mb(expo) to 7mb(react-native cli).
Detach from expo
create new react-native cli project and copy all source from expo to new react-native project.

Upgrade expo version to 31.exporecently launched single-SDK builds for Android. These builds contain only the SDK version the app uses when built and are both faster and slimmer. it helps for smaller standalone app build size. release note

Vote over here so that expo can look into the feature https://expo.canny.io/feature-requests/p/reducing-app-size Problem is react-native uses hermes so the packaging is similar to what native android app from android studio can do but since herme is like latest about 1-2year expo team has not made the support for hermes please vote.. And I also totally agree with #jakobinn

Related

Why, after assembling the .apk file, some functions that work on the local server ( EXPO) do not work in it?

I am developing a React Native mobile application using Expo. The application has a filtering function for certain parameters. When I launch the app via Expo on my device, everything works correctly. However, after building the .apk (I use eas-cli for this purpose) and opening the application on the same (my) device, the filtering function stops working (no errors occur).
how it looks on the Expo server;
how it looks in .apk;
how it looks in .apk;
I don't have any thoughts at all about why this might happen, because everything works correctly on the Expo server.
This is my build file:
{
"build": {
"preview2": {
"android": {
"gradleCommand": ":app:assembleRelease",
"buildType": "apk"
}
},
"production": {}
}
}
the command I use to build:
eas build -p android --profile preview2

Camera: Native Module 'CameraView' was null (react-native-camera-vision)

I'm running an EXPO project (https://mrousavy.com/react-native-vision-camera/docs/guides/#installing-the-library)
I've ran
expo install react-native-vision-camera
added the plugin in my app.json (code below)
expo prebuild
{
"plugins": [
[
"react-native-vision-camera",
{
"cameraPermissionText": "$(PRODUCT_NAME) needs access to your Camera.",
// optionally, if you want to record audio:
"enableMicrophonePermission": true,
"microphonePermissionText": "$(PRODUCT_NAME) needs access to your Microphone."
}
]
]
}
Still getting this issue:
https://i.stack.imgur.com/OpezF.png
EXPO SDK 46
react-native-vision-camera: 2.15.1
Read a bunch of docs saying react-native-vision-camera does not work with Expo - but there are setup docs with expo. Not sure how to move forward from here.
Thanks guys
I've tried running pod install in ios dir, installation was successful but no luck.

What are .tflite files in React Native app bundles and how to remove them

My mobile app is written in React Native and built using Expo as a bundle, then uploaded to Google Play.
Google Play Console warns me about size of the bundle and hints on removing largest files that are these:
assets/models/fssd_100_8bit_gray_v1.tflite (2.49 MB)
assets/models/fssd_100_8bit_v1.tflite (2.45 MB)
assets/models/contours.tfl (1.16 MB)
Does anyone know what these files are and how to remove them from my app bundle? Google tells me that .tflite is for Tensor Flow Lite, but I am sure I am not using it.
These are Face Models used in Face Detection.
You first need to eject to strip those models,
expo eject
Then navigate to app/build.gradle
dependencies {
...
// strip face detection from mlkit
implementation (project(':react-native-camera')){
exclude group: 'com.google.mlkit', module: 'face-detection'
}
...
}
Or, if you don't want MLKit entirely just
edit app/build.gradle
defaultConfig {
...
missingDimensionStrategy 'react-native-camera', 'general'
...
}
These files are for face detection and some gesture related function. These are generated as you are using react-native-camera. If you are not using these functions, You can unlink and uninstall the library and install and link again.
Remember in app/build.gradle use react-native-camera as general
defaultConfig {
.........
........
missingDimensionStrategy 'react-native-camera', 'general'
.........
.........
}
It is working for me, i think it will also work for you.
For me, those libraries were attached with #react-native-firebase/ml
Once I removed #react-native-firebase/ml, my final APK size reduced by 15MB

React native Fabric autolink error with react 60.0 and above

I have upgraded to my app to react-native 60.4 which support Autolinking all packages so that you dont have to manually go about setting things up and thus lowers the chances of error.
The problem is most of the packages have still not gotten compatible with this process and henceforth the app completely breaks.
my error is with https://github.com/corymsmith/react-native-fabric
referring to an issue on the repo for the same -> https://github.com/corymsmith/react-native-fabric/issues/225, which still remains unanswered.
I started giving it a try by forking the repo and understanding the auto link process given by react native.
In the package.json of the node_module package i replaced
"rnpm": {
"android": {
"packageInstance": "new FabricPackage()"
}
},
with file in the package root react-native.config.js
module.exports = {
dependencies: {
'react-native-fabric': {
platforms: {
android: {
"packageImportPath": "import com.smixx.fabric.FabricPackage;",
"packageInstance": "new FabricPackage()"
}
}
}
}
};
I also updated the build gradle to 3.4.1 from 3.1.0
My react native app is able to now find the package.
But when i call the package in my react component i get NoClassDefFoundError, which means that class is not found.
Anybody else gave this a try and have a solution please let me know.
Try to unlink with react-native unlink and then re run your code again.
Putting it here from the above comment to make it more clear:
Ok i got this to work by changing the forked repo -> (adding a react-native.config.js in the root of the package with with auto discovery and link configurations), but i think the only scalable solution i see right now is to degrade to RN ^59.0 as not a lot of packages have auto link config changes. So will wait for RN 60.4 to mature and then upgrade to it in about a month. In addition to this fabric is currently migrating to firebase and plans to complete by year end. This mean that anyways the sdk integration is going to be obsolete and hence this package too.
Also this issue is majorly related to react-native-fabric and not RN itself.

Go back to debugging after created release version with react-native bundle (Android)

So I have created my Application using React native and just produced my first release-build.
My problem now is that I can't get back to react natives debug-mode.
By following the documentation, this is what i did.
react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/
This code generated the bundled index.android.bundle and index.android.bundle.meta
Now every time I execute react-native run-android, the javascript code-base wont update the application and I am not able to access the development(shake) menu in my app.
If I run react-native bundle again, the code will update.
I guess this is a simple issue, but can't find any information how to return so the app isn't using the bundled version anymore.
Delete assets folder in app/src/main/
Remove this import line if exist : "import com.facebook.react.BuildConfig;" in MainApplication.java
Run "react-native run-android"
And boom!
My quickest way is openning the file: $projectRoot\android\app\src\main\java\com\movies\MainApplication.java,
going to the code like:
public boolean getUseDeveloperSupport() {
return false; //it was changed to false from BuildConfig.DEBUG when released
}
then changing the false to true to make the debug menu available again.
It happens with wrong import statement in MainApplication.java,
You have to check if any statement like import com.facebook.react.BuildConfig; is in the imports. If so, remove that and run react-native run-android
No need to delete assets folder