Mobile App

Cara Optimasi Ukuran Aplikasi Flutter: Mengurangi APK & IPA dan Meningkatkan Performa Render

R

Raka Haikal

Tim Teknis Arkatek

·
8 min baca
·
13x dibaca
Ilustrasi Cara Optimasi Ukuran Aplikasi Flutter: Mengurangi APK & IPA dan Meningkatkan Performa Render

Ukuran unduhan aplikasi (download size) berpengaruh langsung terhadap kesuksesan bisnis digital. Studi Google Play berjudul Shrinking APKs, Growing Installs (2017) menemukan bahwa untuk aplikasi di bawah 100 MB, setiap kenaikan ukuran APK sebesar 6 MB berkorelasi dengan penurunan konversi instalasi sekitar 1%, dengan dampak yang lebih besar di pasar berkembang. Datanya memang sudah lama, tetapi logikanya masih berlaku: pengguna dengan kuota terbatas atau memori penyimpanan mepet akan berpikir dua kali sebelum mengunduh aplikasi yang besar.

Selain ukuran berkas, performa render yang tersendat (frame drops atau jank) saat pengguna melakukan scrolling adalah pemicu utama ulasan bintang 1 dan pencopotan pemasangan (uninstall). Panduan ini membahas cara mengukur, memangkas ukuran aplikasi Flutter di Android maupun iOS, dan menjaga render tetap mulus di 60–120 FPS.

Poin Penting / Key Takeaways
  • Ukur dulu dengan flutter build --analyze-size dan DevTools. Ukuran upload package bukan ukuran unduhan pengguna yang sebenarnya.
  • Rilis Android dalam format AAB (wajib untuk aplikasi baru di Google Play). Gunakan --split-per-abi bila harus membagikan APK di luar Play Store.
  • --split-debug-info memangkas ukuran biner, sedangkan --obfuscate menambah proteksi kode tetapi bukan jaminan keamanan. Simpan folder symbols setiap rilis agar crash log tetap bisa dibaca.
  • Aktifkan R8 (minify dan shrink resources) untuk layer Android, kompres aset besar, dan subset font teks kustom secara manual. Icon font sudah di-tree-shake otomatis oleh Flutter.
  • Pindahkan parsing JSON besar ke isolate (Isolate.run atau compute()) dan lakukan profiling di profile mode pada perangkat fisik.

1. Ukur Dulu Sebelum Mengoptimasi Ukuran Aplikasi

Jangan mengukur dari build debug. Build debug membawa overhead hot reload dan debugging sehingga jauh lebih besar dari aplikasi yang diunduh pengguna. Hasil flutter build apk atau flutter build ios standar pun hanyalah upload package: Play Store dan App Store akan memprosesnya ulang dan memecahnya sesuai arsitektur CPU serta densitas layar tiap perangkat, sehingga ukuran berkas yang terlihat tidak sama dengan ukuran unduhan pengguna.

Bedah Isi Aplikasi dengan --analyze-size

Tambahkan flag --analyze-size saat build. Flutter menampilkan ringkasan ukuran per kategori (aset, kode native, pustaka Flutter, dan paket Dart) di terminal, sekaligus menyimpan berkas *-code-size-analysis_*.json yang bisa dibuka di DevTools sampai level fungsi. Anda juga bisa memuat dua berkas JSON dari dua build berbeda untuk membandingkan dampak tiap perubahan.

terminal
BASH
flutter build appbundle --analyze-size
# Buka DevTools, pilih Open app size tool, lalu unggah berkas *-code-size-analysis_*.json
dart devtools
Menghasilkan ringkasan ukuran dan berkas analisis untuk DevTools.

Cek Ukuran Unduhan Sebenarnya di Android

Unggah berkas .aab ke Google Play Console, lalu buka Android vitals → App size. Ukuran unduhan di sana dihitung untuk perangkat XXXHDPI dengan arsitektur arm64-v8a, jadi angka di perangkat pengguna lain bisa sedikit berbeda. Untuk iOS, caranya dibahas di bagian iOS di bawah.

2. Memangkas Ukuran Aplikasi Android

A. Gunakan Android App Bundle (AAB)

Jangan merilis berkas APK universal (fat APK) yang menggabungkan seluruh arsitektur CPU (armeabi-v7a, arm64-v8a, x86_64) ke pengguna Google Play. Google Play sudah mewajibkan format AAB untuk aplikasi baru sejak Agustus 2021. Dengan AAB, Play otomatis memecah paket sehingga pengguna hanya mengunduh binary, aset, dan bahasa yang cocok dengan perangkat mereka.

B. Distribusi di Luar Play Store: Gunakan --split-per-abi

Jika harus membagikan APK langsung ke pengguna atau ke toko aplikasi alternatif, jangan bagikan fat APK. Jalankan flutter build apk --split-per-abi untuk menghasilkan satu APK per arsitektur, lalu bagikan yang sesuai. Dengan begitu pengguna tidak perlu membawa binary arsitektur yang tidak dipakai perangkatnya.

C. Pisahkan Simbol Debug dengan --split-debug-info

Saat membuat build rilis, tambahkan --split-debug-info=./build_symbols. Flag ini memindahkan tabel simbol debug keluar dari biner utama ke folder terpisah sehingga ukuran biner turun. Dokumentasi resmi Flutter menyebut flag ini dapat memangkas ukuran kode secara dramatis.

D. Obfuscation dengan --obfuscate

--obfuscate adalah flag terpisah yang mengganti nama simbol Dart menjadi nama pendek tak bermakna. Ini mempersulit reverse engineering, tetapi bukan jaminan keamanan, dan tujuan utamanya bukan memperkecil ukuran. Flag ini wajib dipasangkan dengan --split-debug-info.

E. Aktifkan R8 (Minify dan Shrink Resources)

R8 bekerja pada layer Android (kode Java/Kotlin dari embedding Flutter dan plugin), bukan pada kode Dart. Kode Dart sudah di-tree-shake oleh compiler AOT pada build profile dan release. Aktifkan minify dan shrink resources pada build type release. Sesuaikan dengan DSL proyek Anda: pada Groovy namanya minifyEnabled dan shrinkResources.

android/app/build.gradle.kts
KOTLIN
1android {
2 buildTypes {
3 release {
4 isMinifyEnabled = true
5 isShrinkResources = true
6 proguardFiles(
7 getDefaultProguardFile("proguard-android-optimize.txt"),
8 "proguard-rules.pro"
9 )
10 }
11 }
12}
Konfigurasi R8 pada build type release.

Uji build rilis setelah mengaktifkannya. R8 dapat menghapus kelas yang dipakai lewat refleksi, sehingga plugin tertentu memunculkan error Missing classes saat build atau crash saat runtime. Solusinya biasanya menambahkan aturan keep di proguard-rules.pro.

OPTIMASI AAB & R8

Penyusutan Ukuran Aplikasi

Ukuran unduhan pengguna berkurang dari 46 MB menjadi hanya 18.5 MB di perangkat konsumen.

60%

3. Memangkas Ukuran Aplikasi iOS

Sama seperti Android, ukuran IPA bukan ukuran unduhan pengguna: App Store menerapkan app thinning sehingga tiap perangkat hanya menerima varian yang dibutuhkan. Dokumentasi Flutter juga mencatat bahwa IPA umumnya lebih besar dari APK. Flag --split-debug-info dan optimasi aset dari bagian lain tetap berlaku di iOS. Untuk memperkirakan ukuran nyata, buat App Size Report dari Xcode:

  1. Jalankan flutter build ipa --export-method development.

  2. Buka archive dengan open build/ios/archive/*.xcarchive.

  3. Klik Distribute App, lalu pilih metode distribusi Development.

  4. Pada App Thinning, pilih all compatible device variants dan aktifkan Strip Swift symbols.

  5. Setelah export, buka berkas App Thinning Size Report.txt untuk melihat proyeksi ukuran per perangkat dan versi iOS.

--analyze-size di iOS Menghasilkan .app, Bukan IPA
Gunakan hasil --analyze-size di iOS hanya untuk membandingkan isi aplikasi secara relatif. Untuk angka yang paling akurat, unggah IPA rilis ke App Store Connect dan baca size report di sana.

4. Optimasi Aset, Font, dan Dependency

  • Hapus aset dan paket yang tidak terpakai: tinjau pubspec.yaml secara berkala. Ringkasan --analyze-size menunjukkan paket Dart mana yang paling besar.

  • Kompres gambar raster: kompres PNG dan JPEG, dan pertimbangkan WebP untuk aset besar.

  • Perhatikan font: Flutter otomatis men-tree-shake icon font (misalnya Material Icons) pada build rilis, tetapi font teks kustom tidak di-subset otomatis. Sertakan hanya weight yang benar-benar dipakai dan pertimbangkan subsetting manual, misalnya dengan fonttools.

  • Ganti raster dengan vektor bila memungkinkan: lihat evaluasi di bawah.

Evaluasi Aset: Gambar Bitmap (PNG/JPG) vs Grafis Vektor (SVG/Lottie)

Keunggulan Vektor & Lottie
  • Ukuran berkas dalam hitungan kilobyte (sangat hemat memori)
  • Kualitas visual tetap sangat tajam di resolusi layar smartphone apapun (zero blur)
  • Animasi kompleks interaktif tanpa perlu mengekspor deretan frame video besar
Pertimbangan
  • Rendering grafis SVG yang memiliki ribuan path node rumit dapat membebani GPU perangkat berspesifikasi rendah

Ringkasan Teknik dan Dampak Relatifnya

Dampak di bawah adalah estimasi relatif, bukan angka pasti. Selalu ukur di proyek Anda dengan --analyze-size.

TeknikPlatformDampak relatifCatatan
AAB (bukan APK universal)AndroidTinggiWajib untuk aplikasi baru di Google Play
--split-per-abiAndroid (APK di luar Play)TinggiTidak diperlukan jika distribusi lewat AAB
--split-debug-infoAndroid dan iOSSedang sampai tinggiSimpan folder symbols setiap rilis
R8 (minify + shrink resources)AndroidSedangUji build rilis, mungkin butuh aturan keep
Kompres aset, WebP, hapus aset tak terpakaiAndroid dan iOSTergantung proyekCek kontribusi aset lewat --analyze-size
Subset font teks kustomAndroid dan iOSTergantung proyekIcon font sudah otomatis di-tree-shake
--obfuscateAndroid dan iOSKecil untuk ukuranTujuannya proteksi kode, bukan ukuran

5. Mengeliminasi Jank Render untuk Animasi Mulus 60/120 FPS

Setiap frame punya anggaran waktu (frame budget): sekitar 16,6 milidetik untuk layar 60Hz dan sekitar 8,3 milidetik untuk layar 120Hz. Jika penyajian sebuah frame melewati anggaran itu, frame terlewat dan pengguna melihatnya sebagai gerakan yang tersendat.

Lakukan Profiling di Profile Mode

Jalankan flutter run --profile pada perangkat fisik, idealnya kelas menengah ke bawah yang mewakili pengguna Anda, lalu buka tab Performance di DevTools. Dari sana terlihat frame mana yang melebihi anggaran, baik di UI thread maupun raster thread. Mode debug tidak representatif untuk mengukur performa.

Penyebab Jank yang Paling Umum

  • Kompilasi shader: mesin grafis Impeller meng-precompile shader sehingga menghilangkan shader compilation jank yang dulu umum pada Skia. Impeller aktif secara default di iOS dan di Android API 29 ke atas. Perangkat Android lama masih dapat memakai Skia, jadi uji juga di perangkat entry-level dan periksa catatan rilis versi Flutter yang Anda pakai karena statusnya terus berkembang.

  • Pekerjaan berat di main isolate: parsing respons JSON berisi ribuan item di isolate utama menyita CPU selama ratusan milidetik dan membuat animasi berhenti seketika.

  • Rebuild widget berlebihan: gunakan const constructor, ListView.builder untuk daftar panjang, dan batasi area widget yang dibangun ulang.

6. Contoh Kode: Parsing JSON di Isolate dan Perintah Build Produksi

Berikut contoh memindahkan parsing payload besar ke isolate latar belakang dengan Isolate.run, cara paling sederhana menurut dokumentasi Flutter. Jika aplikasi Anda juga menargetkan web, gunakan compute() dari package:flutter/foundation.dart agar kode tetap bisa dikompilasi.

lib/core/network/api_parser.dart
DART
1import "dart:convert";
2import "dart:isolate";
3
4// Fungsi murni untuk mem-parsing data transaksi
5List<TransactionModel> _decodeTransactions(String rawResponseBody) {
6 final jsonList = jsonDecode(rawResponseBody) as List<dynamic>;
7 return jsonList
8 .map((e) => TransactionModel.fromJson(e as Map<String, dynamic>))
9 .toList();
10}
11
12// Menjalankan parsing di isolate terpisah agar UI tetap mulus
13Future<List<TransactionModel>> parseLargeTransactionPayload(String rawBody) {
14 return Isolate.run(() => _decodeTransactions(rawBody));
15}
Parsing payload besar di isolate latar belakang menggunakan Isolate.run.

Dan berikut perintah build rilis yang menggabungkan teknik di atas, plus cara membaca stack trace dari build yang di-obfuscate:

terminal
BASH
1# Android (Google Play)
2flutter build appbundle --release --obfuscate --split-debug-info=./build_symbols/android
3
4# Android (APK untuk distribusi di luar Play Store)
5flutter build apk --release --split-per-abi --split-debug-info=./build_symbols/android
6
7# iOS
8flutter build ipa --release --obfuscate --split-debug-info=./build_symbols/ios
9
10# Membaca stack trace dari build yang di-obfuscate
11flutter symbolize --input=stacktrace.txt -d ./build_symbols/android
Perintah build rilis yang dioptimasi dan perintah symbolize untuk crash log.

Hubungan Antara Performa Aplikasi dan Arsitektur

Aplikasi yang ringan dan responsif harus didukung oleh manajemen state yang efisien agar tidak terjadi render ulang (unnecessary rebuilds) pada seluruh pohon widget. Pelajari cara mengisolasi pembangunan ulang widget secara presisi melalui panduan Tutorial Manajemen State Flutter BLoC dan tentukan perbandingan teknologi di artikel Flutter vs Native vs React Native.

SOLUSI TEKNOLOGI ARKATEK

Aplikasi Mobile Perusahaan Anda Lambat atau Berukuran Terlalu Besar?

Diskusikan audit performa aplikasi, optimasi framerate 60 FPS, dan perampingan ukuran biner bersama engineer mobile Arkatek.

Pertanyaan Umum Seputar Optimasi Ukuran Aplikasi Flutter

Kenapa ukuran aplikasi Flutter lebih besar dari aplikasi native?

Aplikasi Flutter bersifat self-contained: paket instalasinya membawa engine, runtime, kode, dan aset sendiri. Ukuran dasar itu tidak bisa dihilangkan sepenuhnya, tetapi bisa ditekan dengan teknik di artikel ini. Untuk membandingkan konsekuensi tiap teknologi, baca Flutter vs Native vs React Native.

Apa beda ukuran berkas upload (AAB/IPA) dengan ukuran unduhan pengguna?

Google Play dan App Store memproses ulang paket yang Anda unggah, lalu memfilter arsitektur CPU dan densitas aset sesuai perangkat pengguna. Karena itu ukuran unduhan sebenarnya harus dicek lewat Play Console (Android vitals) dan App Thinning Size Report atau App Store Connect (iOS).

Apakah --obfuscate memperkecil ukuran aplikasi?

Bukan itu tujuan utamanya. Pemangkasan ukuran datang dari --split-debug-info, sedangkan --obfuscate berfungsi mempersulit reverse engineering dan bukan jaminan keamanan. Keduanya dipakai bersamaan, dan folder symbols wajib disimpan.

Lebih baik merilis AAB atau APK?

Untuk Google Play, gunakan AAB, karena format ini wajib untuk aplikasi baru sejak Agustus 2021. APK tetap relevan untuk distribusi manual atau toko alternatif; pada kasus itu gunakan --split-per-abi agar tidak membagikan fat APK.

Apakah Impeller menghilangkan jank sepenuhnya?

Impeller menghilangkan sumber shader compilation jank, tetapi tidak menyelesaikan pekerjaan berat di main isolate atau rebuild widget yang berlebihan. Profiling di profile mode tetap diperlukan.

Kesimpulan

Mengoptimalkan ukuran dan performa aplikasi mobile bukanlah sentuhan akhir yang dikerjakan terburu-buru sebelum rilis, melainkan disiplin rekayasa yang harus diterapkan sejak awal. Mulailah dengan mengukur menggunakan --analyze-size, pangkas ukuran lewat AAB, --split-debug-info, R8, dan optimasi aset, lalu pastikan render tetap mulus dengan profiling dan pemindahan pekerjaan berat ke isolate. Hasilnya adalah aplikasi yang lebih cepat diunduh dan lebih nyaman dipakai.

Referensi resmi: Measuring your app's size dan Concurrency and isolates di dokumentasi Flutter.

R

// DITULIS OLEH

Raka Haikal

Pengembang perangkat lunak & spesialis arsitektur sistem digital di Arkatek. Berfokus pada pembangunan solusi software scalable, otomatisasi sistem bisnis, dan optimasi performa.

// EKSPLORASI TOPIK

Artikel Terkait Lainnya

Lihat Semua Artikel →