Size matters: Reducing Flutter App size best practices
2.6 million apps in the Google Play store today — no wonder convincing a user to install your app has never been more difficult. As if it wasn’t difficult enough already, plenty of your users have seen this dialogue — probably multiple times — as well:
Let’s assume that you have a retail store and you ship an app to make the shopping experience smoother and quicker. You’ve added AR filters and applied Machine Learning to figure out your user's preferences and to tailor the experience. In other words, you’ve made a freakin’ awesome shopping app! Wow! It even supports Android 4.4 and 8 different languages. Good for you!
Now, how many people (especially from those that have a problem with the device storage space) do you think that they are going to download it if they see the following message?
“more than 337 million smartphone users with limited data plans”
So after all coding part, we do optimization and try to reduce the app size. In terms of optimization each and every bytes matter.
The download completion rate of an app with an APK size of around 10MB will be ~30% higher than an app with an APK size of 100MB
There are many good coding practices and building a stable architecture will help the app to perform better. We can talk about it in detail in another article. Apart from that, there are some common methods and practices that you can implement in your app to make it better.
7 Flutter app Performance Tips
1. Image Asset
In Flutter people uses images from assets folder to display in the app. In development mode, this will be useful as the images are loaded faster. But when you bundle the app these images adds more weight to the app. The solution is of using network images. Upload the images in permanent storage path like AWS or in your website server and use the link to that image in your code.
Also, compress PNG and JPEG files before uploading them to your storage. The free online resource to compress the PNG image is https://compresspng.com/.
2. Use Google Fonts
Initially, the flutter app can have custom font styles only assessing the font file from the assets folder. Similar to images these fonts will also increase app size. The best solution is using
google_fonts a plugin. This plugin 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 variations with your project.
'This is Google Fonts',
It is recommended to use from Material Icons or Cupertino Icons class. From Flutter 1.20, you can add
--tree-shake-icons option to flutter build command, to remove all of the not used icons from the bundle. This will potentially save the size of your app.
But in many situations due to modern design you might need to use other icons. In that case use .svg format icon so you don’t need to worry about different device DPI’s and this also helps in reducing apk size.
4. Dynamic App Delivery
We could build an app bundle if we are uploading to playstore or we could split the apk per abi which splits the apk to x64 and x86 bit code. By using appbundle Google Play’s new app serving model, called Dynamic Delivery, uses your app bundle to generate and serve optimized APKs for each user’s device configuration, so they download only the code and resources they need to run your app.
But some of the stores like Amazon App store still doesn’t support appbundle in that case you can use
--split-per-abi command which will give you three version of apks.
On average, apps published with app bundles are 20% smaller in size.
flutter build appbundle
// or use
flutter build apk --split-per-abi
Using cache will not help in reducing app size but it will make the app to load faster and hence improving the app performance. All frequently used images like profile pic, bg picture using
The cached_network_image package allows you to use any widget as a placeholder. In this example, display a spinner while the image loads.
imageBuilder: (context, imageProvider) => Container(
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
Proguard is a java program optimizer. It is not specific to Flutter. It optimizes your code in ways that don’t change the functionality but change the representation to make it more compact. It obfuscates name of types, fields, methods where the original name doesn’t matter such that long names are replaced with short strings like a and b for efficiency. Packages and classes may have a long name but should not hinder efficiency. It also removes unused java code from dependencies.
You have two default proguard file you can apply.
- proguard-android-optimize.txt — progurard configuration
We used proguard-android-optimize.txt as the default proguard configuration. You can add you custom proguard configurations in proguard-rules.pro file in your /app directory.
//Enable the proguard
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), "proguard-rules.pro"
signingConfig playStoreConfig //Add your own signing config
minifyEnabled to true, the proguard will remove all the unused methods, instructions and slim down the classes.dex file.By enabling the proguard in every module of our project we can we are able to reduce the classes.dex file size almost by 50%.
Learn more about proguard here.
7. Use Specific Libraries
Calling packages not needed or used in our pubspec.yaml file should be avoided. Once done building your app, you should check your pubspec.yaml and remove libraries/packages which is/are not used. Also remove all the unused assets from pubspec.yaml.
Also in certain situations due to unavailability of some features me might used some 3rd party plugins. But in some future update Flutter might have resolved it and had a built-in solution. In those case using default Flutter solution is a good practice than using the 3rd party plugins.
Need your support
Follow me on Linkedin, GitHub, and Medium.
You can connect me to firstname.lastname@example.org .