4 min read

Size optimization in React Native

Author

Luka Patrun

Date

Category

Development

Size optimization in React Native Banner

In today's world speed is the king. We have become spoiled for speed and not having to wait for anything and this also applies to mobile apps.

At collective mind, we strive to make our apps with optimization in mind. By that we are considering a couple of things like bundle size, in app performance and all of it has speed in common. By being considerate when making apps, we can make them both performant and future proof.

So without further ado I would like to invite you to continue reading this article where we will start with a blank app and we will investigate what we can do to reduce app size.

REACT NATIVE

In order to test our changes we will start by creating new react native application. I will create one using the typescript template but it doesn't make any difference if you make one without typescript:

npx react-native init MyApp --template react-native-template-typescript

With this we have a starting point. Before making any changes I want to make a RELEASE version of this empty app.

Default app

To create APK which I can install on my device I will run

cd android && ./gradlew assembleRelease

inside my terminal. This will initialize app generation which I can find in

android/app/build/outputs/apk/release

As you can see on the next image, the size of the starter react native app without optimization is 18,6 MB.

Default app APK

And for something that has only some text on it and couple of links, I believe you will agree with me, ii is just too much.

Default app Home page

Let's just check how big the app is once it is installed.

Default app Home page

As visible from the screenshot the app is 37,08 MB in size. Even though new smartphones have more than enough space to download and install apps this big hundreds of time, that doesn't mean we should stop at this.

CPU Architecture

Just like PC CPUs have different architectures, so do mobile phones. But what exactly does that mean to us and what can we do about it?
For us to be able to install "traditional" APK to all sorts of devices, gradle has to make that one version and make sure it will run on a lot of devices. To battle this we have an option to make builds for each of the architecture out there and by doing that we don't need unnecessary overhead we have by building only one APK.

Inside

android/app/build.gradle

you must enable enableSeparateBuildPerCPUArchitecture.

... def enableSeparateBuildPerCPUArchitecture = true ...

and if we create release one more time we will see 4 APKs in our release folder.

Separate build per CPU architecture

Now with four possibe APK we must install only the supported one on our device. If you are having a newer device you should be installing the "app-arm64-v8a-release.apk". If you are unsure which one to install you can either install every until one can actually install and run or you can go ask the almighty Google for help.

Alright, alright, alright, now I will install the APK so we can see if there is any improvement and how big the difference it is.
As visible from the image below, we have just saved 11,14 MB of space.

Separate build per CPU architecture

This might not be a lot in numbers but this means our App is now 30% smaller than the original one with just one small change.

If you are going to upload your app to the app store, make sure to generate and upload an ".abb" file type to get even better results.

Read more about this on Developer Android.

After this little optimization one thing has crossed my mind:

MORE

why stop here. Next up

Proguard

To quote React Native docs
"Proguard is a tool that can slightly reduce the size of the APK. It does this by stripping parts of the React Native Java bytecode (and its dependencies) that your app is not using."

To enable proguard we will go back to build.gradle and enable it:

... def enableProguardInReleaseBuilds = true ...

and let's assemble new APK's and take a screenshot of them.

Proguard on

Before focusing on v8a APK I want to emphasize just how much x86_64 APK has lost in size. It is down to just 6,2 MB from 29,9 MB and that is a reduction of a whopping 80%.
On the other hand, the v8a instance has reduced from 7,5 MB to 5,9 MB which is a reduction of 22%. Here you can read more about Code shrinking.

And the installed app is now:

Proguard on

more than 6 MB smaller than without proguard.

Oh yeah, one more thing.

Shrink resources

I almost forgot to mention shrinkResources. This will be the last optimisation we will make in this post. This actually works only in conjunction with code shrinking. After the code shrinking has removed all unused code, resources could be shrunk as well.
So the order will be:

  • • minify will shrink our code, i.e. remove all unused code,
  • • shrink will actually remove all resources that are no longer needed.

Turn on shrinkResources:

... minifyEnabled enableProguardInReleaseBuilds shrinkResources true ...

the minifyEnabled will get its value from the enableProguardInReleaseBuilds. Drumroll please, let's check the final results before the summary.

The APK sizes are:

Proguard on

the same as without shrinkResources set to true.

But what about if we install it.

Proguard on

There is a difference of about 0.01 MB, which is nice.
Even though the results are somewhat disappointing, they make sense because this project is pretty empty.

Summary

Firstly I want to thank you if you came to the end.

To recap everything, I have made a small graph to summarize all the data.

Summary chart

With proguard and With resource shrink lines have actually merged together.

That's it for this post, make sure to check later for new ones.