メモパチのバージョンアップ対応の一環で、ローカルデータベースライブラリをhiveからhive_ceに差し替えた。APIの互換性があり、コード変更はほぼなかった。ところが、ビルド後のiPAファイルが約10MB小さくなっていた。
意図していない削減だったので最初は驚いたが、調べると理由はシンプルだった。ライブラリが内部で使っていたネイティブバイナリが消えたからだ。
なぜ軽くなったか
hiveとhive_ceの根本的な違い。
hive(オリジナル)は2021年ごろから更新が止まり、事実上メンテナンスが放棄された状態にある。hive_ceはコミュニティがフォークして引き続き保守しているバージョンだ。単なる後継ではなく、内部実装が書き直されている部分がある。
最大の違いはネイティブバイナリの扱いだ。旧hiveはiOS・Android向けのプラットフォームコードを含んでいた。これはパフォーマンス向上を目的とした実装だが、その分バイナリサイズが大きくなる。hive_ceはこの部分をPure Dart(Dartのみ)で書き直しており、ネイティブバイナリへの依存がない。
iOSのIPAビルドは依存ライブラリのネイティブコードをそのままバイナリに組み込む。Pure Dartに置き換えれば、その分のコードがそのまま削減される。10MBという数字は、hiveのネイティブ実装が占めていた量だ。移行コストがほぼゼロで10MB削れるなら、乗り換えない理由はない。
移行時の注意
hive → hive_ce はAPIがほぼ互換だが、細かい挙動差異がバージョンによって存在する。移行後は既存データの読み書きが壊れていないかを必ず確認すること。特にカスタムTypeAdapterを書いている場合は要テスト。まずやること
何が重いかを先に把握する。
闇雲に削減策を試す前に、現状のサイズを測ることから始めるべきだ。Flutterにはビルドサイズを分析するオプションが用意されている。
// Android向け(iOS向けは--analyze-sizeを--target-platform ios-arm64に変えて実行)
flutter build apk --analyze-size
実行するとパッケージ・アセット・フレームワーク別のサイズがツリー形式で表示される。「このパッケージがこんなに重かったのか」という発見が必ずある。削減の優先順位を決める上で有効だ。
軽量化の手法
試せることを、まとめて並べる。
hive_ce移行以外にも、Flutterアプリのサイズを削減する方法はいくつかある。
-
--obfuscate + --split-debug-info
リリースビルド時にDartコードを難読化し、デバッグシンボルを外部ファイルに分離する。コードサイズが数MB単位で減ることがある。分離したシンボルはクラッシュレポートの解析に必要なので、捨てずに保管しておく。
flutter build ipa --obfuscate --split-debug-info=./debug_symbols
-
使っていないパッケージを外す
pubspec.yamlに残ったまま使われていないライブラリはないか確認する。
flutter pub depsで依存ツリーを確認できる。直接は使っていないが間接依存で引っ張られているケースも多い。削減できる場合はpubspec.yamlから削除してpub getしなおす。 -
アセットの最適化
アプリに含まれる画像は圧縮されているか確認する。PNGはTinyPNGなどで圧縮。使われていない画像ファイルも案外残っている。アイコンフォントはFlutterのtree-shakingが効いて、使用していないアイコンはリリースビルドで自動的に除外される(
--tree-shake-iconsはデフォルトON)。 -
Androidは --split-per-abi
通常のAPKビルドは複数CPUアーキテクチャ(arm64-v8a, armeabi-v7a, x86_64)のコードをまとめて含む。アーキテクチャ別に分割すると、ユーザーは自分の端末に必要な分だけダウンロードする仕組みになる。Play Storeで配布する場合は特に効果的。
flutter build apk --split-per-abi
-
deferred loading(遅延読み込み)
使用頻度の低い大きな機能を、最初のロード対象から外す手法。Dart の
deferred as構文で実装できる。設定画面やヘルプ画面など、起動時には不要な機能を対象にすると、初回起動に必要なコードを削減できる。実装コストはあるが効果は大きい。
まとめると
まず--analyze-sizeで何が重いかを把握する。その上でライブラリの見直し・ビルドオプション・アセット最適化の順に手を入れると効率がいい。hive_ceへの移行はコストがほぼゼロで効果が大きい選択肢だった。