DEV Community

Cover image for Reducing App Size in Flutter: Best Practices
مصعب يوسف
مصعب يوسف

Posted on Originally published at systemweakness.com on

Reducing App Size in Flutter: Best Practices

Reducing App Size in Flutter: Best Practices

As mobile developers, we strive to deliver smooth and efficient user experiences, and a significant part of this involves managing the size of our apps. Flutter apps, by default, may have a larger size compared to native apps due to Flutter’s engine and dependencies. However, several best practices can help reduce the size of your Flutter app and make it more lightweight. In this article, we will cover methods like removing unused assets and code, using ProGuard to optimize and shrink your Flutter app, and other advanced techniques to ensure your app remains as lean as possible.

Removing Unused Assets and Code

One of the simplest ways to reduce the size of your Flutter app is to remove unused assets and code. Over time, during the development cycle, an app can accumulate unnecessary assets, such as images, icons, or even libraries that are no longer in use. Removing these items can significantly reduce the final app size and enhance overall performance.

Identifying Unused Assets

Unused assets can take up a lot of space in your Flutter app, especially if they are high-resolution images or large files. To identify unused assets, you can manually go through your pubspec.yaml file to see which assets are declared but not used in the code. While this can be tedious, it is highly effective in reducing app bloat.

You can also use tools like flutter_clean_architecture to identify unused assets and remove them from your project. Keeping only the assets that are actually in use can reduce the overall size of your app. Regular asset cleanups are recommended, especially after major development milestones, to ensure that no redundant files remain.

Removing Dead Code

Dead code, which includes functions, classes, or entire packages that are no longer in use, can unnecessarily bloat your application. Tools like Dart DevTools can help you profile your application and identify dead code. Once identified, remove unused imports, classes, and functions to make your app cleaner and smaller.

It is a good practice to regularly conduct code reviews to ensure that no unnecessary libraries or classes are left in the project. This practice not only helps reduce the size of the app but also improves the maintainability of the codebase. Code reviews also help identify unused dependencies, ensuring that every package or library used adds value to the project.

Additionally, consider using Dart’s linter to automatically identify unused code and enforce code quality standards. Linting tools can be added to your CI/CD pipeline, making it easier to maintain clean and optimized code throughout the development process.

Using ProGuard to Shrink Your App

ProGuard is a popular tool for reducing the size of Android apps by removing unused code and resources and obfuscating the code. When building Flutter apps for Android, ProGuard can be an effective tool to reduce APK size.

How to Enable ProGuard in Flutter

To enable ProGuard in your Flutter project, follow these steps:

  1. Open the android/app/build.gradle file.
  2. Update the buildTypes block to enable ProGuard for release builds.
buildTypes {
    release {
        // Enable shrinking, obfuscation, and code optimization
        minifyEnabled true
        useProguard true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. You can customize ProGuard rules by editing the proguard-rules.pro file in your Android project. By adding rules to exclude certain classes or libraries, you can optimize your app while still retaining necessary functionality.

Enabling ProGuard helps reduce the app size by removing unused classes and methods from your project. Moreover, the obfuscation process makes it harder for anyone to reverse-engineer your code, adding a layer of security. Obfuscation also helps protect intellectual property, which is particularly important for commercial apps.

R8: An Alternative to ProGuard

R8 is another tool provided by Google that is used to shrink, obfuscate, and optimize your Android code. In fact, R8 is now the default code shrinker for Android projects, replacing ProGuard. You can use R8 with your Flutter app without any additional configuration, as it is integrated into the Android Gradle plugin. To use R8, just make sure minifyEnabled is set to true in the build.gradle file.

R8 offers better performance than ProGuard and can provide a smaller APK size while reducing build time. Unlike ProGuard, R8 integrates the shrinking, obfuscation, and optimization processes into a single step, leading to more efficient builds. The advantage of R8 over ProGuard lies in its integration with the D8 dexer, which further helps minimize the app size.

Split the APK by ABI

When building Flutter apps for Android, by default, all the native libraries are bundled into a single APK. This significantly increases the APK size. To reduce the size, you can split the APK by ABI (Application Binary Interface). This way, users will only download the version of the APK that matches their device’s architecture.

To split the APK by ABI, modify the android/app/build.gradle file:

android {
    // ...
    splits {
        abi {
            enable true
            reset()
            include 'armeabi-v7a', 'arm64-v8a', 'x86_64'
            universalApk false
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

With this configuration, Flutter will generate separate APK files for each architecture, resulting in smaller download sizes for end users. This approach not only reduces the download size but also ensures that users get a version of the app optimized for their device. Splitting APKs by ABI also reduces the likelihood of compatibility issues, as users receive an APK specifically designed for their hardware.

Additionally, you can use App Bundles instead of APKs. The Google Play Store uses app bundles to serve optimized APKs, which contain only the resources and native libraries that match the user’s device, thereby reducing the size of the downloaded app.

Compressing Images and Assets

High-resolution images are often one of the biggest contributors to large app sizes. To reduce the size of your Flutter app, it is essential to compress images and other assets without compromising too much on quality. Here are a few ways to achieve this:

  1. Image Compression Tools: Use tools like TinyPNG, ImageOptim, or Squoosh to compress your images before adding them to your project. Compressed images take up less space and help reduce the overall app size.
  2. WebP Format: Use WebP instead of traditional image formats like PNG or JPEG. WebP offers excellent compression while maintaining good quality. Many modern browsers and Android versions support WebP, making it a great option for image assets.
  3. SVG for Vector Graphics: If your images are simple icons or vector shapes, consider using SVG. SVGs are scalable and typically smaller in size compared to raster images. SVG assets are ideal for icons and logos that need to maintain sharpness across different screen sizes.

Reducing the size of images can have a noticeable impact on the overall size of your app, particularly if your project includes many high-resolution images. Additionally, you can use Flutter’s built-in flutter_image_compress package to further reduce the size of images during runtime.

You can also consider lazy loading images that are not immediately needed. By only loading images when they are required, you can reduce memory consumption and improve the initial load time of your app, further enhancing the user experience.

Removing Unnecessary Packages and Plugins

Another important aspect of reducing app size is removing unnecessary packages and plugins. Flutter’s rich ecosystem provides a vast number of packages, but including too many of them can lead to a bloated app size. Go through your pubspec.yaml file and remove any plugins or packages that are not essential for your app's functionality.

If you only need a small portion of functionality provided by a package, consider finding a lighter package or implementing that specific feature yourself. This way, you avoid adding unnecessary dependencies that could contribute to a larger app size. Always aim to minimize dependencies and opt for lightweight libraries whenever possible.

Another effective approach is to modularize your app. Break down your app into modules and only include specific dependencies in the relevant modules. This way, you avoid adding unnecessary dependencies to the entire app, which helps keep the app size smaller.

Flutter Build Modes: Use flutter build apk --release

When testing your app during development, Flutter builds it in debug mode, which includes additional metadata and debugging tools that increase the app size. To reduce the app size, always use the release build for production.

Use the following command to build your Flutter app in release mode:

flutter build apk --release
Enter fullscreen mode Exit fullscreen mode

Release mode optimizes the code and removes unnecessary metadata, resulting in a much smaller app size. It also removes the debugging tools, making the app more secure and efficient for end users. The release build includes code optimizations that ensure better performance and a faster startup time for your app.

Furthermore, consider enabling code shrinking and tree shaking during the release build process to eliminate unused code and resources. This will help in keeping the release APK as optimized as possible.

Additional Techniques for Reducing App Size

  1. Lazy Loading Assets: Only load assets when they are needed. For example, load images or other assets when they are about to be displayed, rather than preloading everything at startup.
  2. On-Demand Code Loading: Use on-demand code loading techniques to split the app’s code into smaller modules that load only when required. This can be particularly useful for features that are not needed during the initial app load.
  3. Tree Shaking: Tree shaking is a method of eliminating unused code. Flutter uses Dart’s tree shaking during compilation, which ensures that only the necessary code is included in the final build. Regularly refactor and clean up your codebase to maximize the benefits of tree shaking.
  4. Use Lightweight State Management Solutions: When choosing state management solutions for your app, opt for lightweight ones like Provider or Riverpod instead of heavier alternatives. Lighter state management solutions can reduce the app’s memory footprint and contribute to a smaller app size.
  5. Minimize Animations and Effects: Although animations can make your app visually appealing, they often contribute to larger app sizes, especially if they rely on external libraries. Where possible, use Flutter’s built-in animation capabilities and minimize dependencies on third-party animation libraries.

Best Practices Summary

  1. Remove Unused Assets and Code: Regularly review and clean up assets, imports, and packages.
  2. Enable ProGuard or R8: Use these tools to shrink, obfuscate, and optimize your code.
  3. Split APK by ABI: Generate separate APKs for different architectures to reduce the download size.
  4. Compress Images and Assets: Use image compression tools and consider modern formats like WebP or SVG.
  5. Remove Unnecessary Packages: Only include packages that are absolutely necessary for your app’s functionality.
  6. Use Release Build: Always build your app in release mode for production to optimize app size.
  7. Lazy Loading and On-Demand Code: Load assets and code modules only when required to save memory.
  8. Tree Shaking: Ensure unused code is removed during compilation by keeping your codebase clean.
  9. Modularize Your App: Divide your app into modules to minimize dependencies and reduce overall app size.
  10. Use Lightweight Libraries: Choose lightweight state management solutions and minimize the use of heavy animations and effects.

Conclusion

Reducing the size of your Flutter app can improve performance, enhance the user experience, and lead to higher download and retention rates. By following these best practices — removing unused assets, using tools like ProGuard or R8, splitting the APK by ABI, compressing images, and cleaning up unnecessary packages — you can significantly reduce the size of your Flutter app. Additionally, using techniques like lazy loading, tree shaking, on-demand code loading, and modularization can further optimize your app’s performance.

Start optimizing today to make your app leaner and faster, offering a better experience to your users. A well-optimized app not only provides smoother performance but also increases the likelihood of positive user feedback and higher ratings on app stores, ultimately contributing to the success of your application. Remember, reducing app size is an ongoing process, and keeping your codebase clean and efficient will help maintain an optimized app in the long run.

Top comments (0)