如何低成本的降低Flutter包体容量

前言

在产品的运营期间,我们发现Android用户对App容量大小的敏感度明显高于iOS用户。

所以,为了提升产品在市场中竞争力,进一步提升产品的下载量,我们需要对基于Flutter开发的Android客户端进行包体优化。

经过调研,我们发现Flutter经过多年的发展后,DevTools已经完善,用较低的低成本即可满足需求。

下面我们会从分析开始,了解不同构成部分的容量分布情况。再对构成部分的特性来决定最终如何进行包体优化。

生成分析报告

首先,在build产物时,我们可以加上 --analyze-size 标识来生成分析报告。apk 和 appbundle 还可以指定产物的平台架构,如:--target-platform android-arm,分析实际机型的情况。

# 变异产物
# Specify one of android-arm, android-arm64, or android-x64 in the --target-platform flag.
flutter build apk --analyze-size --target-platform android-arm64
flutter build appbundle --analyze-size --target-platform android-arm64

apk 分析日志

app-release.apk (total compressed)                                         33 MB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  assets/
    dexopt                                                                  1 KB
    flutter_assets                                                          5 MB
  classes.dex                                                               7 MB
  lib/
    arm64-v8a                                                              18 MB
    Dart AOT symbols accounted decompressed size                            8 MB
      package:flutter                                                       3 MB
      package:image                                                       799 KB
      dart:core                                                           325 KB
      package:xxx_xxx_flutter                                             293 KB
      dart:ui                                                             279 KB
      dart:typed_data                                                     226 KB
      dart:io                                                             212 KB
      dart:collection                                                     177 KB
      package:vector_graphics_compiler                                    170 KB
      dart:async                                                          154 KB
      package:flutter_localizations                                       129 KB
      package:flutter_spinkit                                              99 KB
      package:extended_image                                               93 KB
      dart:ffi                                                             85 KB
      package:petitparser                                                  73 KB
      dart:convert                                                         62 KB
      package:archive                                                      62 KB
      package:dio                                                          57 KB
      package:vector_math                                                  54 KB
      package:riverpod                                                     49 KB
  AndroidManifest.xml                                                       3 KB
  res/
    -j.png                                                                  4 KB
    1k.png                                                                 33 KB
    1r.png                                                                 91 KB
    2M.png                                                                  3 KB
    33.9.png                                                                2 KB
    3m.png                                                                  1 KB
    4C.png                                                                  1 KB
    4F.png                                                                 10 KB
    AQ.png                                                                 33 KB
    Bj.png                                                                 29 KB
    CG.png                                                                 23 KB
    Ch.png                                                                 98 KB
    D2.png                                                                 14 KB
    E7.png                                                                 98 KB
    EA.png                                                                 98 KB
    ER.9.png                                                                2 KB
    FM.9.png                                                                1 KB
    Fo.png                                                                 29 KB
    G1.png                                                                  2 KB
    J6.9.png                                                                2 KB
    JO.png                                                                 29 KB
    Mr.9.png                                                                1 KB
    NF.png                                                                  6 KB
    Ni.png                                                                 33 KB
    ON.png                                                                 91 KB
    Pi.9.png                                                                3 KB
    Q11.9.png                                                               3 KB
    RX.png                                                                 16 KB
    S9.png                                                                  2 KB
    SD.png                                                                  5 KB
    Tu.png                                                                 10 KB
    Vq.png                                                                  1 KB
    Vw.png                                                                 71 KB
    WR.png                                                                 30 KB
    XU.png                                                                  1 KB
    Yj.png                                                                  4 KB
    _C.png                                                                  3 KB
    _f.png                                                                  2 KB
    bI.png                                                                  3 KB
    color-v23                                                               2 KB
    color                                                                  16 KB
    dn.png                                                                  2 KB
    e1.xml                                                                  1 KB
    eB.9.png                                                                2 KB
    fM.png                                                                  5 KB
    fR.png                                                                 67 KB
    gV.9.png                                                                1 KB
    jy.png                                                                  8 KB
    nN.png                                                                  4 KB
    qt.png                                                                  2 KB
    tj.9.png                                                                2 KB
    u3.png                                                                  3 KB
    wi.9.png                                                                2 KB
    wi1.9.png                                                               1 KB
    wn.png                                                                 10 KB
    x4.png                                                                  3 KB
    yT.png                                                                  1 KB
    zT.png                                                                 91 KB
  resources.arsc                                                          926 KB
  client_analytics.proto                                                    1 KB
  dc/
    a.gz                                                                   37 KB
  kotlin/
    collections                                                             1 KB
    kotlin.kotlin_builtins                                                  5 KB
    ranges                                                                  1 KB
    reflect                                                                 1 KB
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
A summary of your APK analysis can be found at: /Users/xxx/.flutter-devtools/apk-code-size-analysis_01.json

To analyze your app size in Dart DevTools, run the following command:
dart devtools --appSizeBase=apk-code-size-analysis_01.json

appbundle 分析日志

app-release.aab (total compressed)                                         18 MB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  BUNDLE-METADATA/
    assets.dexopt                                                           1 KB
    com.android.tools.build.libraries                                       8 KB
    com.android.tools.build.obfuscation                                   628 KB
  base/
    assets                                                                  5 MB
    dex                                                                     3 MB
    lib                                                                     8 MB
    Dart AOT symbols accounted decompressed size                            8 MB
      package:flutter                                                       3 MB
      package:image                                                       799 KB
      dart:core                                                           325 KB
      package:xxx_xxx_flutter                                             293 KB
      dart:ui                                                             279 KB
      dart:typed_data                                                     226 KB
      dart:io                                                             212 KB
      dart:collection                                                     177 KB
      package:vector_graphics_compiler                                    170 KB
      dart:async                                                          154 KB
      package:flutter_localizations                                       129 KB
      package:flutter_spinkit                                              99 KB
      package:extended_image                                               93 KB
      dart:ffi                                                             85 KB
      package:petitparser                                                  73 KB
      dart:convert                                                         62 KB
      package:archive                                                      62 KB
      package:dio                                                          57 KB
      package:vector_math                                                  54 KB
      package:riverpod                                                     49 KB
    manifest                                                                4 KB
    res                                                                     1 MB
    resources.pb                                                          292 KB
    root                                                                   51 KB
  META-INF/
    UPLOAD.SF                                                              46 KB
    UPLOAD.RSA                                                              1 KB
    MANIFEST.MF                                                            34 KB
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
A summary of your AAB analysis can be found at: /Users/xxx/.flutter-devtools/aab-code-size-analysis_01.json

To analyze your app size in Dart DevTools, run the following command:
dart devtools --appSizeBase=aab-code-size-analysis_01.json
✓ Built build/app/outputs/bundle/release/app-release.aab (18.2MB).

解读分析报告

使用DevTools解读报告

这里以 VS Code DevTools 举例(Install and run DevTools from VS Code

image-20230627103050073

以上图为例,appbundle在未压缩的情况下, 体积为23.1MB,其中base占据了主要的容量。

base中占据主要大小的分别有lib (8MB)、assest (5MB)、dex (3MB)、res (1.2MB)。

分析内容物可以得出:

除去这些主要的文件内容,剩余的多位配置文件,所占容量的比例也不大,可优化空间不大。

可探索的优化方向

第一步,通过优化素材可以直接减少包体内容的大小。

第二步,减少不必要的代码模块。

下面介绍下Flutter提供的精简代码功能。

精简代码

在build产物时,添加 --obfuscate--split-debug-info 来实现对代码的混淆,以及对代码的精简。

# 指定android-arm64平台,在当前路径输出符号表(如`app.android-arm64.symbols`)
flutter build appbundle --target-platform android-arm64 --split-debug-info=. 

未精简的日志

flutter build appbundle --target-platform android-arm64                           

Running Gradle task 'bundleRelease'...                          
Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 3124 bytes (99.8% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app.
Running Gradle task 'bundleRelease'...                             26.7s
✓ Built build/app/outputs/bundle/release/app-release.aab (18.2MB).

精简后的日志

flutter build appbundle --target-platform android-arm64 --split-debug-info=. 

Running Gradle task 'bundleRelease'...                          
Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 3124 bytes (99.8% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app.
Running Gradle task 'bundleRelease'...                             56.6s
✓ Built build/app/outputs/bundle/release/app-release.aab (17.6MB).

开启混淆的日志

flutter build appbundle --target-platform android-arm64 --split-debug-info=.  --obfuscate

Running Gradle task 'bundleRelease'...                          
Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 3124 bytes (99.8% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app.
Running Gradle task 'bundleRelease'...                             57.5s
✓ Built build/app/outputs/bundle/release/app-release.aab (17.6MB).

读取混淆的堆栈跟踪

如需要调试被混淆的应用程序创建的堆栈跟踪,请遵循以下步骤将其解析为可读的内容:

flutter symbolize -i <stack trace file> -d out/android/app.android-arm64.symbols

总结

在素材和代码模块的两个方向上进行包体优化,是比较容易操作,并且不会影响App稳定性的方案。

在出包的工作流中,我们会启用精简代码以及代码混淆,优化产物中代码所占的体积。

排查已经引入的依赖库,看是否存在未使用或者已经弃用的多余依赖。同时分析占容量较大的三方依赖,判断是否需要通过精简定制来降低容量。

最终是排查素材,筛选体积,对不达标的素材进行重新制作,或者寻找替代方案,比如改用网络资源。

参考

Obfuscating The Flutter App

Mastering Dart & Flutter DevTools — Part 3: App Size Tool

Reducing Flutter App Size

Using the app size tool