Measure and optimize your Flutter app size
Tags: flutter, tutorial, android, ios
Published: 2024-06-19 02:43:21


When creating mobile apps, a competent mobile engineer must consider the applications' quality as well as its functionality to ensure that users have a positive experience. This goes beyond simply producing a product that functions as intended.

Some of the things we need to pay attention are, performance, application size, stability, security, compatibility, scalability, and maintenance. In this post, we'll talk about one component of quality: application size. Specifically, we'll go over how to measure the size of our app and optimize it to the perfect user size.

---

## 🛠  Measuring Flutter app size
To begin analyzing and measuring the size of our Flutter applications, we can use the Flutter analysis tool by passing the --analyze-size parameter when building. In this example, I'm going to illustrate how to analyze it on the Android app bundle, and then the command we can do is

```
flutter build appbundle --analyze-size --target-platform=android-arm64
```

Leave it until it's done, and we'll get the app size breakdown (Android App Bundle) on our app.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tsd7daowjl18goa0n7h1.png)

The tool displays a high level summary of the size breakdown in the terminal, and leaves a `*-code-size-analysis_*.json` file. To do a deeper analysis, we can use the results generated by our JSON file on Dart Dev Tools. To do it first, we need to activate and run Flutter Dev Tools by performing the following command

```
flutter pub global activate devtools; flutter pub global run devtools
```

When we run the Flutter dev tools, we can open the Flutter dev tools on our localhost at http://127.0.0.1:9100/.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rd4a57ej1h12vtm81eb0.png)

After that, go to the "App Size Tooling" section and do the JSON file import that we have generated previously.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6nwhwfe1u08w0esas768.png)

Here we can see in detail the size distribution of our applications, which makes it easy for us to determine which parts are our focus in doing app size optimization.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/904x9qruswdrzgir49m9.png)

---

## 📊 Optimizing Flutter app size
Once we've done measuring on our application, we can proceed to optimize. With the details we got from the measuring, we could focus on optimizing parts that have significant sizes.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ulb30bhtfyeujrc5gqfr.png)

In the example of this application, we can see that the largest contributor size is lib, followed by assets, and finally dex. 


**Optimizing Dex File**
DEX file is a compiled file format for the Dalvik Virtual Machine, which is the virtual machine that Android used to run applications. DEX stands for Dalvik Executable, and these files have a .dex extension. They contain compiled code written in the Java programming language that can be executed on the Android platform. In the context of Flutter, while your primary code is in Dart, any integration with Android's native functionality will involve DEX files for the Java/Kotlin components.

On applications that aren't too complex and don't use a lot of third-party libraries, dex files should not be that big. From there, we can optimize dex files in our application. There are several ways to reduce the size of our DEX files, such as: 

**1. ProGuard/R8 Obfuscation and Shrinking**

ProGuard and R8 are tools provided by Android to help shrink, obfuscate, and optimize your code. R8 is the default compiler for Android that includes ProGuard’s capabilities.

In your `gradle.properties` file, ensure ProGuard or R8 is enabled:

```properties
android.useProguard=true
```

Enable code shrinking and obfuscation in `build.gradle`:

```gradle
buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
```

**2. Enable Multidex**

MultiDex facilitates the separation of code into smaller modules. This can be combined with App Bundles or Split APKs to optimize which parts of the app are downloaded and installed on the user’s device. For instance, if parts of your app are only needed by certain users, these can be separated into different DEX files, potentially reducing the download size for users who don’t need all features.

In your `build.gradle` file, ensure multiDexEnabled is enabled:

```gradle
android {
    defaultConfig {
        multiDexEnabled true
    }
}
dependencies {
    implementation 'androidx.multidex:multidex:2.0.1'
}
```

**3. Split APKs**

In your `build.gradle` file, ensure you include different ABIs (Application Binary Interfaces).

```gradle
android {
    splits {
        abi {
            enable true
            reset()
            include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
            universalApk false
        }
    }
}
```

After doing some optimization, we can go back to build analysis on our application to see the differences that occur after implementation.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vfs3r8yalx0an1m5xgzz.png)

Here you can see that after implementation, our dex files experienced a significant decline of about 59.57% from 9.4 MB to 3.8 MB.


**Optimizing Assets File**

Next is assets. Assets are often the cause of the swelling of an application. The use of inappropriate asset images, such as images with too large resolutions, which are actually not needed on applications, becomes a common cause. 

In the problem example of this time, we assume all the images already have the appropriate measurement that is needed in an application. Then what can we do to optimize our file assets? After checking back, the asset used in this project is to use image assets with extensions jpg and png. We can change this standard to the latest extension that is more optimum in terms of compression, namely WebP.

WebP is designed to provide better image compression with an image quality equivalent to or better than other image formats.

WebP Advantages:

- Better Compression Quality:
WebP typically provides smaller file sizes with equal or better image quality compared to other image formats such as JPEG and PNG.

- Transparency:
WebP supports alpha transparency, which allows it to be a good alternative to the PNG image format.

- Animation
WebP supports animation, making it a good alternative to the GIF image format.

After making changes to the image format in our application, we can rebuild the image size and see how much of a decrease happens to our assets.

Before:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owm17nvvx19i5iy2tm30.png)

After:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l5l3hrjxqb2vjq0ldx7f.png)

After we checked back on the analyzing tools, it turned out there was an asset-size increase, not a decrease. Don't worry, it turns out when we use WebP they might appear to have a larger size when analyzed with `flutter analyze`. This might seem counterintuitive since one of the main advantages of WebP is its superior compression compared to other image formats like PNG or JPEG.

The `flutter analyze` tool might interpret the size of the WebP images differently than other image formats. It might consider the uncompressed or maximum size of the image when calculating the size, leading to the appearance of a larger size.

So how do we know if the optimization of changes to our app is either to optimize our app size or to add more content to our app? Here we can take advantage of the Google Play app size analyzer, where Google Play does provide app download size breakdowns.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/83mvzkhbojumgll5cvd7.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e7erdks39gfdly0w10r5.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cesqvwoe0xocxec9grpk.png)

Here you can see that after implementation, our assets files experienced a significant decline of about 48.67% from 12 MB to 6.16 MB.

---

## 🌟 Conclusion

By measuring app size on our app, we can figure out the size distribution that happens on our application, and it makes it easy for us to focus on what needs to be optimized based on the breakdown size of our app.

---

## 📄 References

- [Measuring your app's size](https://docs.flutter.dev/perf/app-size)