Size Matters!? Shaving Size of Your Flutter App

Probably APK (or app bundle) and IPA size is not something that is causing you sleepless nights. At least it isn’t for me.

We know that there are some tradeoffs when going cross-platform route. Most of people will name performance or look-and-feel as main concerns. Maybe some will mention the deliverable size. This is what I will tackle in this blog post. The size of your app for the end user.

Of course, going the cross-platform route we accept that our deliverable would be bigger. The main reason is that platform does not provide the runtime for our out app. We always need to ship everything to start and run our app.

Why should you care about your download size? In most cases there are two, three, or thirty other apps that will do exactly the same thing as yours. If your potential user need to wait one more minute to install yours app, this is potential one minute when he/she can give a try for a competitor app. This is also more time when something may go wrong, more bytes to transfer means higher probably that something will go wrong with the internet connection etc.

Also smaller app size may be a factor for the Play/AppStore listing. As Apple/Google needs to push all of that data to the user and they need to pay for the upload 😀 (just kidding ;)). But anyway, at least Play Console shows how your APK size compares to the app category median.

Some basic things you can find in this blog post, I will cover all the rest ;). Would recommend you go over this blog first, configure progurad etc. and get back here for more!

R8

This is Android specific. It is a successor to proguard, that can also remove not used resources. You can enable it by adding android.enableR8=true to android/gradle.properties (although it may be already enabled). One thing to note is that it may remove not used resources, like eg. your notification icon, please follow instructions from flutter_local_notifications in order to keep your notification icon.

Fonts

If your app uses custom fonts, I would recommend finding alternatives in Google Fonts, and then adding google_fonts to your dependencies. You may wonder how additional dependency may reduce your APK size? Well, first of all you may remove all other fonts from your project. Secondly google_fonts will dynamically download font when it is used and it will download it in a specific style and language, so that you don’t need to ship all of the variation with your project. Yes, this is another tradeoff, most probably fonts will be downloaded on app initial start… but it is less bytes to push when app is installed.

Icons

You probably use a few icons either from Icons or CupertinoIcons class. Normally this means that all of the icons are embedded into your Flutter bundle. But since flutter 1.17, you can add --tree-shake-icons option to flutter build command, that would remove all of the not used icons from the bundle. Few more bytes shaved!

Split Debug Info

You probably don’t want to include Dart debug information in your production release. --split-debug-info is another option you can add to flutter build command to store debug information separately. This option takes additional argument that is a directory where debug information should be stored.

In case of my HabitChallenge app, I have created a git submodule, where I automatically store, and tag, debug information after the release.

Then when you need to add debug information to your stacktrace, you can use flutter symbolize command and point to appropriate version of debug-info.

Putting All Together

In my case, I have created bash scripts that handle the release process (let me know if you are interested to know how I do releases for HabitChallenge).

Android

For android things are fairly easy, since you can manually upload APK(s) or App Bundle to Play Console (or point fastline to do it for you automatically).

Continue reading