Reducing Flutter App Size | 5 Things I’ve Learnt

Jackie Moraa
4 min readFeb 17, 2025

--

As someone who barely has any storage space on their phone due to an insane amount of cat photos and videos, getting small-sized apps on the PlayStore is always a dream.

Image Source

Flutter apps can sometimes become unnecessarily large due to a number of things e.g., unused code, large images etc. Therefore, reducing app size is crucial especially for users with limited storage (like me) and bandwidth. This article will look at some techniques I have learnt to shrink Flutter apps. Let’s get into it.

Optimise image assets

Images and icons are almost unavoidable in app development. But at the same time, they contribute significantly to app size. Unoptimsed image assets occupy a lot of space and inflate the app size. You can optimise them by:

  • Using Scalable Vector Graphics (SVGs) instead of raster images (PNGs, JPEGs or JPGs). Because SVGs are vector based, they occupy less space than their counterparts. Another advantage of SVGs is they maintain the crisp quality when scaled. This is especially useful in responsive development as the need to have multiple assets for different devices is eliminated (SVGs are responsive by default)
  • Using WebP instead of raster images. WebP is an open-source image format developed by Google which focuses on creating smaller, higher-quality images to make the web faster. WebP lossless images are 26% smaller in size compared to PNGs, offering significant advantages in terms of web performance and bandwidth usage.
  • Compress SVGs and WebP images. An extra step after opting to use SVGs or WebPs is to compress them. There are various online tools to perform this compression without compromising its quality.

Use ProGuard for Android

ProGuard optimises apps by reducing their size and improving performance, ensuring a more efficient and seamless user experience. It is not specific to Flutter but it shrinks any Java or Kotlin related code.

Enable ProGuard in android/app/build.gradle

android {
buildTypes {
release {
...
proguardFiles (getDefaultProguardFile('proguard-android-optimize.txt')),
'proguard-rules.pro'
}
}
}

Add ProGuard rules in that proguard-rules.pro file to prevent essential code from being stripped away. (Kinda like .gitignore which is used to exclude certain files in your directory from your Git history).

Enable tree shaking

Tree shaking refers to the process of eliminating unused code or dependencies from the final compiled bundle of an application. During the development process, various packages are imported to add required functionalities to the app. But sometimes, not all the code from these packages are necessary or used in the application.

So, tree shaking will analyse the codebase to identify the “dead” code and eliminate it. The result of this process is a smaller and more optimised compiled app bundle.

Code obfuscation

Code obfuscation is the process of making code more difficult to reverse-engineer. This is what is most commonly used for — to add a layer of security and protection for the app. However, another nice thing about this process is that it reduces app sizes. This is because obfuscation will renames symbols and shorten class names and method names to make the code harder to read and this results in reduced file sizes. So it’s like a 2 for 1 special.

Run flutter build apk — release — obfuscate — split-debug-info=debug_info/ to obfuscate your release apk and generate a symbols map.

--obfuscate: Will enable the obfuscation.
--split-debug-info=debug_info/: Will store the symbols in the debug_info/ directory which will allow you to debug your obfuscated app in the future.

Make sure to backup the symbols file. If you lose the original file, you can use the backup to de-obfuscate a stack trace.

Generating a Split APK

By default, Flutter will generate a single apk which will have the binaries for all architectures (ARM, ARM64, and x86). This has the benefit that the single apk will run on multiple architectures and thus has wider compatibility, but the drawback is that its file size is much larger and users will download and store more bytes when installing your application than they need to. So, if generating apks instead of app bundles (which is now recommended by Google Play), it is strongly recommended to build split APKs. Thus, generate a separate apk for each architecture and upload them to the PlayStore. Run: flutter build apk — release — split-per-abi

--split-per-abi: This generates a separate apk for each Application Binary Interface (abi). The supported target architectures: armeabi-v7a (ARM 32-bit), arm64-v8a (ARM 64-bit), and x86–64 (x86 64-bit).

The PlayStore delivery system will then detect the architecture of the downloading phone and serve it with the right apk.

The techniques discussed above (and others not mentioned here) can be implemented to significantly reduce app bloat and ensure a lightweight build. And as an end user, this is music to my ears!

“Less is more.”
— Ludwig Mies van der Rohe

If you made it to this part, as always, thank you for reading ❤

--

--

Jackie Moraa
Jackie Moraa

No responses yet