Tüm Yazılar
KategoriFlutter
Okuma Süresi
14 dk
Yayın Tarihi
2024-11-12
Kelime Sayısı
2.903kelime

Kahveni hazırla - bu içerikli bir makale!

Flutter Uygulama Boyutunu Küçültme: APK ve IPA Rehberi

Özet

Flutter uygulama boyutu küçültme için --analyze-size, --split-debug-info, --obfuscate, split APK ve app bundle stratejilerini resmi dokümantasyona dayanarak adım adım anlatan pratik rehber.

  • Önce flutter build apk --analyze-size ile bir baseline al; ölçmeden yapılan hiçbir optimizasyona güvenme.
  • --split-debug-info kod boyutunu dramatik şekilde küçültebilir; --obfuscate ile birlikte kullanılabilir.
  • Play Store dağıtımında app bundle, Play Store dışı kanallarda --split-per-abi fat APK'dan daha küçük dosyalar üretir.
  • iOS'ta App Thinning Size Report projeksiyon bir boyut verir; kesin boyut için release IPA'yı App Store Connect'e yükleyip oradaki raporu almak gerekir. IPA'lar engine farkı nedeniyle genelde APK'lardan büyüktür.
Flutter Uygulama Boyutunu Küçültme: APK ve IPA Rehberi

Flutter uygulama boyutu küçültme konusuna girmeden önce şunu net söylemek gerekiyor: "neden benim APK'm komşu takımınkinin üç katı" sorusunun cevabı çoğu zaman tek bir ayarda değil, birikimli üç kaynakta gizlidir — Flutter engine'in kendisi, Dart AOT derlemesinin dahil ettiği kod ve projeye eklenen asset'ler. Bu rehberde --analyze-size, --split-debug-info, --obfuscate, --split-per-abi ve app bundle stratejilerini resmi Flutter dokümantasyonuna dayanarak, adım adım ve ölçülebilir şekilde ele alıyoruz.

💡 Pro Tip: Boyut küçültmeye başlamadan önce mutlaka flutter build apk --analyze-size çalıştırıp bir referans (baseline) al — hangi değişikliğin gerçekten işe yaradığını, spekülasyon değil, sayıyla göreceksin.

İçindekiler

Uygulama Boyutu Nereden Geliyor?

Bir Flutter release build'inin boyutu üç ana bileşenden oluşur: Flutter engine'in kendisi (C++ ile yazılmış, Skia/Impeller render katmanını içerir), Dart Ahead-of-Time (AOT) derleyicisinin ürettiği makine kodu ve uygulamana eklediğin görsel/font/JSON gibi asset'ler. Bunlardan ilk ikisi platform ve mimariye göre değişse de temelde sabittir; asıl kontrol edebileceğin alan, kendi kodun ve asset'lerindir.

Debug build'ler burada yanıltıcı bir referans noktasıdır. Flutter'ın resmi dokümantasyonu şunu açıkça belirtir: debug build boyutu, hot reload ve kaynak seviyesinde debug desteği sağlayan ek yük (overhead) nedeniyle büyüktür ve production boyutunu temsil etmez. Yani "debug APK'm 80 MB" diye panik yapmadan önce mutlaka flutter build apk --release ile üretilmiş bir dosyaya bakmalısın.

Dart AOT ve Tree-Shaking Nasıl Çalışır?

Dart compiler, release build sırasında agresif bir tree-shaking uygular: eğer bir kod yolu derleme zamanında hiçbir zaman çalışmayacağı kanıtlanabiliyorsa, o kod nihai binary'e dahil edilmez. Resmi dokümantasyondaki klasik örnek, dart:io içindeki Platform sınıfıyla yazılan platforma özgü kontrollerdir: Windows'a özel bir kod bloğunu Platform.isWindows koşuluyla sararsan ve uygulamayı Android için derlersen, compiler bu koşulun her zaman false olduğunu görür ve Windows'a özgü kodu release build'den tamamen çıkarır. Bu, "yazdığın her satır boyuta eklenir" varsayımının her zaman doğru olmadığını gösteriyor — asıl mesele, o kodun derleme zamanında elenebilir olup olmadığı.

  • Engine payı: platform runtime'ı + render katmanı, projeden projeye büyük ölçüde sabit
  • Dart AOT payı: kendi kodun + bağımlılıkların derlenmiş hali, tree-shaking'e açık
  • Asset payı: görseller, fontlar, JSON/lottie dosyaları — genelde en kolay küçültülebilen katman

DevTools App Size Aracıyla Ölçüm

Tahmin yürütmek yerine ölçmek için Flutter'ın kendi built-in aracını kullan. Flutter 1.22 ve DevTools 0.9.1'den beri gelen boyut analiz aracı, release build'in tam bir dökümünü çıkarır ve bunu DevTools arayüzünde görselleştirir.

Komut, birden fazla platform hedefini destekler:

bash
1# Android APK için boyut analizi
2flutter build apk --analyze-size
3 
4# Android App Bundle için boyut analizi
5flutter build appbundle --analyze-size
6 
7# iOS için boyut analizi
8flutter build ios --analyze-size
9 
10# Masaüstü hedefleri
11flutter build linux --analyze-size
12flutter build macos --analyze-size
13flutter build windows --analyze-size

Bu komut çalıştırıldığında terminale bir boyut özeti basılır ve ek olarak bir *-code-size-analysis_*.json dosyası üretilir (örneğin ~/.flutter-devtools/apk-code-size-analysis_01.json). Bu JSON dosyasını DevTools'un "App Size" sekmesine yükleyerek treemap ve tablo görünümünde detaylı bir inceleme yapabilirsin.

App Size aracının iki sekmesi vardır: tek bir anlık görüntüyü incelediğin Analysis ve iki anlık görüntüyü karşılaştırdığın Diff. Analysis sekmesindeki kod-atıf görünümleri:

  • Dominator tree: bir kod parçasının binary'de _neden_ yer aldığının kök nedenini anlamak için kullanılır
  • Call graph: bir kod parçasına giden/ondan çıkan tüm çağrı yollarını görmek için kullanılır

Diff sekmesi ise iki farklı --analyze-size çıktısını (örneğin optimizasyon öncesi ve sonrası) karşılaştırıp farkı treemap ve tabloda görselleştirmek için kullanılır.

Pratik iş akışı şu şekilde işler: optimizasyon öncesi bir JSON al, değişikliği yap, tekrar --analyze-size çalıştır, iki dosyayı Diff sekmesinde karşılaştır. Bu, "bu değişiklik gerçekten 2 MB kazandırdı mı yoksa hissim mi öyle" sorusunu sayıyla cevaplar.

--split-debug-info ve --obfuscate ile Kod Boyutunu Küçültmek

Resmi dokümantasyon, kod boyutunu küçültmek isteyenlere doğrudan --split-debug-info bayrağını öneriyor ve bunun kod boyutunu _dramatik şekilde_ azaltabileceğini belirtiyor. Bu bayrak, debug sembol bilgisini binary'nin dışına, ayrı bir dizine taşır; böylece uygulamanın kendisi bu sembolleri taşımaz ama sen crash raporlarını yine de sembolize edebilirsin.

bash
1# Debug bilgisini ayrı bir dizine taşı (boyut küçültme)
2flutter build apk --release \
3 --split-debug-info=build/debug-info
4 
5# Aynı şeyi obfuscation ile birlikte yap
6flutter build apk --release \
7 --obfuscate \
8 --split-debug-info=build/debug-info

Obfuscation (--obfuscate) yalnızca release build'de çalışır ve dokümantasyonun açıkça uyardığı gibi kaynakları şifrelemez, ters mühendisliği tam olarak engellemez — sadece sembol isimlerini daha anlaşılmaz hale getirerek okunabilirliği zorlaştırır. Obfuscation, doğrudan boyutu küçültmek için tasarlanmamıştır ama --split-debug-info ile birlikte kullanıldığında ikisi de release pipeline'ının standart bir parçası haline gelir.

Obfuscation'ın desteklendiği build hedefleri arasında apk, appbundle, ios, ios-framework, ipa, linux, macos, macos-framework, windows ve aar bulunuyor — yani hem mobil hem masaüstü hem de framework/AAR paketleme senaryolarında kullanılabilir. Web uygulamaları ise obfuscation'ı desteklemez; onun yerine minification uygulanır, bu da benzer bir "okunabilirliği azaltma" etkisi sağlar.

⚠️ Dikkat: Obfuscation aktifken çöken bir uygulamanın stack trace'ini çözmek için --split-debug-info ile ürettiğin sembol dosyalarını mutlaka güvenli bir yerde (örneğin CI artifact deposunda) saklaman gerekir; aksi halde crash raporların anlamsız isimlerle dolu gelir.

ABI'ye Göre Split APK mı, App Bundle mı?

Android tarafında boyutu doğrudan etkileyen en büyük karar, hangi mimariler (ABI) için derleme yaptığındır. Varsayılan olarak bir app bundle, Dart kodunu ve Flutter runtime'ını armeabi-v7a (ARM 32-bit), arm64-v8a (ARM 64-bit) ve x86-64 mimarilerinin _hepsi_ için derlenmiş halde barındırır.

Bayraksız (varsayılan) bir flutter build apk komutu, tüm bu mimarileri tek bir dosyada birleştiren "fat APK" üretir. Fat APK, geniş cihaz uyumluluğu sağlar ama dosya boyutu, tek bir mimariye özel bir APK'dan çok daha büyüktür. Dokümantasyon burada net bir tavsiye veriyor: Play Store dışına dağıtım yapılsa bile --split-per-abi bayrağıyla split APK üretmek güçlü şekilde öneriliyor.

bash
1# Fat APK (tüm ABI'ler tek dosyada, en büyük boyut)
2flutter build apk --release
3 
4# Split APK (her ABI için ayrı, küçük dosya)
5flutter build apk --release --split-per-abi
6 
7# App Bundle (Play Store'un önerdiği format, en verimli teslimat)
8flutter build appbundle --release

--split-per-abi kullanıldığında üç ayrı APK dosyası üretilir: biri armeabi-v7a, biri arm64-v8a, biri de x86_64 için. Burada bir ayrıntıya dikkat etmek gerekiyor: split APK'lar kullanılırken Flutter framework'ü, version code'a otomatik olarak ABI_VERSION * 1000 ekler. Bu, Play Store'un aynı version code ile birden fazla APK yüklemeyi reddetmesini önlemek içindir.

Boyut küçültmenin Android tarafındaki bir diğer katmanı da kod küçültücüdür (shrinker). Google'ın kod küçültücüsü (code shrinker) R8, release APK veya AAB derlemesinde varsayılan olarak etkindir; --[no-]shrink bayrağının bir etkisi yoktur, çünkü kod küçültme release build'de kapatılamaz (dokümantasyonun kendi notu). R8'in bir diğer dolaylı faydası da dex method limitiyle ilgilidir: minSdk 20 ve altını hedefleyen projelerde, çok sayıda paket veya geniş bir kod tabanı kullanıldığında Android'in 64k method dex limitine takılma riski artar. Flutter tooling bu durumu otomatik olarak tespit eder, multidex build hatasını yakalar ve Android projende gerekli değişiklikleri yapmadan önce senden onay ister — yani bu senaryoda elle bir yapılandırma aramana genelde gerek kalmaz.

Google Play Store ise Ağustos 2021'den beri yeni uygulamaların Play'de App Bundle formatıyla (AAB) yayınlanmasını zorunlu tutuyor ve resmi dokümantasyon da app bundle'ı APK yerine dağıtım formatı olarak öneriyor; çünkü Play Store, kullanıcının cihazına özel APK'yı sunucu tarafında dinamik olarak üretip yalnız o cihaza gereken parçaları teslim ediyor — yani split APK'nın manuel olarak yaptığın işi Play Store, App Bundle ile otomatik yapıyor.

Format
Kim üretir
Kullanıcıya inen dosya
Ne zaman tercih edilir
Fat APK
flutter build apk
Tüm ABI'leri içeren tek dosya
Play Store dışı test/dağıtım, hızlı prototip
Split APK
flutter build apk --split-per-abi
Cihazın ABI'sine uygun tek dosya
Play Store dışı dağıtım kanalları (sideload, kurumsal)
App Bundle
flutter build appbundle
Play Store'un dinamik ürettiği optimize paket
Play Store üzerinden resmi dağıtım (varsayılan öneri)

Görsel Asset Stratejisi: Çözünürlük Varyantları

Asset'ler, çoğu projede kod kadar (bazen daha fazla) boyut kaplar. Flutter'ın pubspec.yaml dosyasında assets: altına bir dizin (directory/) belirterek klasördeki tüm dosyaları toplu şekilde dahil edebilirsin; bu, tek tek dosya eklemekten daha az hataya açıktır ama dizindeki her şeyin build'e girdiğini de unutmamak gerekir.

Çözünürlüğe duyarlı asset (resolution-aware asset) mekanizması, Flutter'ın en köklü özelliklerinden biridir ve cihazın piksel yoğunluğuna göre doğru varyantı otomatik seçer:

  • my_icon.png: temel (mdpi) çözünürlük
  • 1.5x/my_icon.png: hdpi cihazlar için
  • 2.0x/my_icon.png: xhdpi cihazlar için
  • 3.0x/my_icon.png: xxhdpi cihazlar için
  • 4.0x/my_icon.png: xxxhdpi cihazlar için

Bu yapı, "her cihaza tek bir dev görsel gönder, Flutter otomatik küçültsün" yaklaşımından çok daha verimlidir; çünkü runtime'da ölçeklendirme yapmak yerine, doğru boyuttaki dosya doğrudan indirilir/paketlenir. Ben genelde düşük yoğunluklu varyantları elle üretmek yerine en yüksek çözünürlükten (3.0x veya 4.0x) başlayıp gerektiğinde küçültmeyi tercih ederim; bu sayede kalite kaybı minimumda kalıyor.

iOS Tarafında IPA Boyutunu Ölçmek

iOS tarafında boyut ölçümü, Android'den biraz farklı bir akış izler. Xcode'un "Distribute App" akışını (App Thinning) çalıştırdığında üretilen dizinde App Thinning Size Report.txt adlı bir dosya bulunur; bu dosya, uygulamanın farklı cihaz ve iOS sürümlerindeki _projeksiyon_ boyutunu detaylı şekilde listeler. iOS uygulamasının kesin boyutunu ölçmek için tek güvenilir yol, bir release IPA'yı App Store Connect'e yükleyip boyut raporunu oradan almaktır.

bash
1# iOS için release IPA üret, obfuscation ve debug-info split ile
2flutter build ipa \
3 --release \
4 --obfuscate \
5 --split-debug-info=build/ios-debug-info

Dokümantasyon, iOS release build'lerinde de --obfuscate ve --split-debug-info bayraklarının eklenmesini, Dart kodunu ters mühendisliğe karşı daha zor hale getirmek için öneriyor — bu, Android tarafındaki tavsiyeyle birebir aynı mantık.

Sık karşılaşılan bir soru da şu: neden benim IPA dosyam APK'mdan daha büyük? Flutter'ın resmi dokümantasyonu bunun genel bir örüntü olduğunu doğruluyor: IPA'lar, Flutter engine'in platformlar arası boyut farkı nedeniyle APK'lardan yaygın olarak daha büyük çıkar. Bu, senin kodunla ilgili bir sorun değil, iki platformun engine paketleme biçimindeki yapısal farktır — dolayısıyla "Android'de 12 MB, iOS'ta 22 MB" gibi bir sonuç görürsen önce panik yapma, App Size raporuyla gerçek dağılıma bak.

Paket Bağımlılıklarını Boyuta Göre Denetlemek

pubspec.yaml'a eklediğin her paket, potansiyel olarak boyuta kod ve asset ekler — ama bunu tahmin etmek yerine ölçmek çok daha güvenilir. Burada devreye DevTools App Size aracındaki dominator tree görünümü giriyor: bir paketin (veya paket içindeki belirli bir sınıfın) binary'de neden yer aldığının kök nedenini bu görünümde görebilirsin.

Pratik denetim akışı şöyle işler:

  1. flutter build apk --analyze-size ile mevcut durumun JSON'ını üret
  2. JSON'u DevTools App Size aracına yükle, treemap'te en büyük payı alan paketleri tespit et
  3. Dominator tree'de şüpheli bir paketi seçip hangi importun onu binary'ye dahil ettiğini incele
  4. Kullanılmayan veya çok daha hafif bir alternatifi olan paketi kaldır/değiştir, tekrar --analyze-size çalıştır
  5. İki JSON'u Diff sekmesinde karşılaştırıp gerçek kazancı doğrula

Bu döngü, "bu paket büyük görünüyor, kaldıralım" gibi sezgisel kararlar yerine, her değişikliği ölçülebilir bir kanıta bağlar — özellikle büyük ekiplerde, "boyutu kim şişirdi" tartışmalarını sayıyla bitirmenin tek güvenilir yolu budur.

Adım Adım Boyut Küçültme Kontrol Listesi

Her uygulamanın asset yükü, bağımlılık grafiği ve hedef ABI seti farklı olduğu için tek bir genel önce/sonra tablosu yanıltıcı olur; kendi tablonu aşağıdaki adımları izleyip yukarıdaki DevTools akışıyla kendin üretmen gerekir.

Adım
Uygulanan optimizasyon
Beklenen etki
1
--analyze-size ile baseline ölç
Ölçüm yok = optimizasyon yok
2
--split-debug-info ekle
Kod boyutunda dramatik azalma (dokümantasyonun kendi ifadesi)
3
flutter build appbundle (fat APK yerine)
Play Store'un cihaza özel teslimatı, kullanıcı indirmesinde küçülme
4
--split-per-abi (Play Store dışı dağıtımda)
Fat APK'ya göre önemli ölçüde küçük tek-ABI dosyalar
5
Asset'leri çözünürlük varyantlarıyla organize et
Gereksiz büyük görsellerin runtime'da taşınmasını önler
6
Dominator tree ile bağımlılıkları denetle
Kullanılmayan/ağır paketlerin tespiti ve kaldırılması

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?

Okuyucu Ödülü

Aşağıdaki listeyi bir sonraki release öncesi kontrol listesi olarak kullanabilirsin; her madde bu yazıda anlatılan, dokümantasyonla doğrulanmış bir adıma karşılık gelir.

SSS

Flutter uygulaması neden bu kadar büyük?

Boyutun büyük kısmı üç kaynaktan gelir: Flutter engine'in kendisi, Dart AOT derlemesinin dahil ettiği kod ve projeye eklenen asset'ler. Bunlardan engine payı platform bazında büyük ölçüde sabittir; en çok kontrol edebileceğin alanlar kendi kodun (tree-shaking'e açık) ve asset'lerindir. Debug build'e bakarak boyut değerlendirmesi yapmak yanıltıcıdır, çünkü debug build hot reload desteği için ek yük taşır.

Flutter APK boyutu nasıl küçültülür?

En etkili üç adım sırasıyla: --split-debug-info bayrağıyla debug sembollerini binary dışına taşımak (dokümantasyonun "dramatik azalma" dediği adım), Play Store dışı dağıtımda --split-per-abi ile fat APK yerine ABI'ye özel split APK üretmek ve Play Store dağıtımında doğrudan app bundle kullanmaktır. Bunların etkisini --analyze-size ile ölçmeden yapılan hiçbir değişikliğe güvenme.

App Bundle ile split APK arasındaki fark nedir?

Split APK, senin --split-per-abi ile manuel olarak ürettiğin, her biri tek bir ABI'ye ait ayrı dosyalardır ve Play Store dışı dağıtım kanalları için uygundur. App Bundle ise Play Store'un kendisinin, kullanıcının cihazına göre dinamik olarak ürettiği optimize paket formatıdır; Google Play Store resmi olarak APK yerine app bundle kullanılmasını önerir çünkü kullanıcıya daha verimli bir teslimat sağlar.

Flutter'da hangi asset'ler boyutu şişiriyor?

En sık boyut şişiren kalemler, çözünürlük varyantı olmadan tek büyük dosya olarak eklenen görsellerdir. pubspec.yaml'da bir dizini toplu olarak assets: altına eklemek pratik olsa da, dizindeki her dosyanın build'e dahil olduğunu unutmamak gerekir; kontrolsüz büyüyen bir asset klasörü, kod tarafındaki tüm optimizasyonları gölgede bırakabilir. DevTools App Size aracının treemap görünümü, hangi asset'in gerçekten en büyük payı aldığını doğrudan gösterir.

Güncelleme (Eylül 2026)

Bu yazı 2024-11-12 tarihindeki Flutter sürümüne göre yazıldı. O tarihten bu yana render ve tasarım katmanında iki doğrulanmış değişiklik oldu: Flutter 3.47 ile birlikte Impeller, masaüstü platformlarda (macOS, Linux, Windows) varsayılan render motoru haline geldi — debug'da --no-enable-impeller bayrağıyla, dağıtımda ise platforma özgü bir ayarla (macOS: Info.plist'te FLTEnableImpeller, Linux: fl_dart_project_set_enable_impeller, Windows: set_impeller_switch) eski davranışa dönülebiliyor, ama bu opt-out'un ileride kaldırılması planlanıyor (kaynak: docs.flutter.dev/perf/impeller). Aynı sürümle birlikte Material ve Cupertino tasarım kütüphaneleri çekirdek SDK'dan ayrılarak package:material_ui ve package:cupertino_ui adlı bağımsız pub.dev paketleri haline geldi; bu paketlere geçiş isteğe bağlı ve dart fix --apply --code=migrate_design_widgets komutuyla otomatikleştirilebiliyor (kaynak: docs.flutter.dev/release/breaking-changes/material-ui-and-cupertino-ui). Bu iki değişiklik doğrudan APK/IPA boyut rakamlarını etkileme iddiası taşımıyor; ama render motoru veya tasarım paketi geçişi yapan projelerin, bu yazıdaki --analyze-size akışını geçiş sonrası tekrar çalıştırıp yeni bir baseline alması mantıklı olur.

Sonuç

Flutter uygulama boyutunu küçültmek, tek bir sihirli bayrak değil, ölçüm alışkanlığı meselesidir: önce --analyze-size ile baseline al, sonra --split-debug-info ve gerekirse --obfuscate ile kod tarafını sıkılaştır, Play Store dağıtımında app bundle'ı tercih et, Play Store dışı kanallarda --split-per-abi kullan ve asset'lerini çözünürlük varyantlarıyla düzenle. Runtime performansı tarafında da benzer bir ölçüm disiplinine ihtiyacın varsa Flutter performans optimizasyonu rehberimize bakabilirsin; iOS tarafında eşdeğer bir boyut küçültme akışı için iOS uygulama boyutu optimizasyonu yazımız da bu makaleyle doğrudan tamamlayıcıdır. Mimarinin baştan doğru kurulması da boyut disiplinini kolaylaştırır; bu konuda Flutter clean architecture rehberi ve Flutter test stratejisi rehberi faydalı olacaktır. Firebase gibi ağır SDK'ları projeye eklerken boyut etkisini önceden değerlendirmek istiyorsan Flutter Firebase entegrasyon rehberimize göz atabilirsin. Uygulama açılış hızını da boyutla birlikte ele almak istersen iOS uygulama açılış optimizasyonu yazımız bu rehberle aynı ölçüm felsefesini paylaşıyor.

Kaynaklar

Etiketler

#Flutter#APK#IPA#app bundle#DevTools#obfuscation#performans#Android
Muhittin Çamdalı

Muhittin Çamdalı

Lead Mobile Engineer

12+ yıllık deneyime sahip Lead Mobile Engineer. Swift, SwiftUI, Kotlin ve Flutter ile iOS, Android ve cross-platform mimarilerde uzman. Performanslı ve kullanıcı dostu mobil uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

İlgili İçerik