内容提要
文章讨论Flutter混合开发下的包体积优化。iOS端分析App.framework与Flutter.framework构成,通过删依赖、混淆、去符号减包,并将快照数据段、flutter_assets、icudtl.dat改为远端加载,同时定制引擎编译裁剪Skia与BoringSSL,使安装体积从18.7MB降至11.8MB。Android端无审核限制,可动态下发libapp.so、libflutter.so等全部产物,减掉约6.2MB。
延伸解读
iOS 减包的核心约束:审核规则决定可挪范围
文章指出,App Store 审核条例不允许动态下发可执行二进制代码,因此 iOS 端只能将四个 AOT 快照中的两个数据段(kDartIsolateSnapshotData 与 kDartVmSnapshotData)改为远端加载,而两个指令段必须留在产物内。这解释了为何 iOS 减包需要修改 Dart VM 启动时的快照读取路径,而不能像 Android 那样直接挪走全部产物。理解这一约束,有助于判断哪些减包手段在 iOS 上可行、哪些不可行。
引擎定制编译:收益明确但操作链路较长
文章将 Flutter.framework 视为体积最大的部分,并给出两条优化路径:编译参数从 -Os 改为 -Oz 可减约 700KB;裁剪 Skia 可减约 200KB,移除 BoringSSL 可减约 500KB(前提是使用客户端代理请求,不再需要 Dart HttpClient)。但定制引擎需要 fork Flutter Engine、修改依赖 commit 并填入 DEPS 与 .gclient,再用 gclient、gn、ninja 完成编译。这意味着减包收益与维护成本需要一并权衡。
Android 端减包更彻底,但依赖动态下发能力
由于没有 App Store 审核限制,Android 端可以挪走 libapp.so、libflutter.so、flutter_assets 等全部 Flutter 产物并发布到云端,再通过定制 flutter.jar 中的 FlutterLoader.java 加载自定义路径的库。文章测得空白宿主工程可完全减去约 6.2MB 的 Flutter 产物体积。不过,这一方案的前提是具备可靠的动态下发与加载链路,文章未展开其失败回退或版本管理细节,实际落地时需自行评估。
体积数据需区分口径,避免误读减包成效
文章提醒,Mac Finder 显示体积因按 1000 而非 1024 换算会偏大;iOS 本地构建分析报告提供的是未加密的安装包体积与解压后体积,上传 App Store 后还会加密,用户最终看到的是 Install Size。文章以空白宿主工程上传 App Store 测得 Install Size 从 18.7MB 降至 11.8MB。读者在对比不同减包方案时,应确认双方使用的是同一体积口径,否则容易高估或低估实际效果。
Q&A
Flutter 在 iOS 端打包后体积偏大,具体是哪些文件占用了空间?
iOS 端 Flutter 产物主要由 App.framework 和 Flutter.framework 构成。App.framework 包含 App(Dart 代码 AOT 产物)和 flutter_assets(静态资源);Flutter.framework 包含 Flutter(引擎二进制)和 icudtl.dat(国际化数据)。其中引擎二进制体积最大。
iOS 上如何通过删除和移动产物来减小 Flutter 包体积?
删产物:移除未使用的依赖库、混淆 Dart 代码(减少约 0.75MB)、删除堆栈跟踪符号(减少约 1.8MB)和 dSYM 符号表(减少约 5.8MB)。挪产物:将快照数据段(kDartIsolateSnapshotData 和 kDartVmSnapshotData)、flutter_assets、icudtl.dat 改为远端加载,需修改 Dart VM 启动时的加载路径。
为什么 iOS 端不能像 Android 那样动态下发所有 Flutter 产物?
因为 App Store 审核条例不允许动态下发可执行二进制代码。因此 iOS 端只能下发快照的数据段(kDartIsolateSnapshotData 和 kDartVmSnapshotData),而指令段(kDartIsolateSnapshotInstructions 和 kDartVmSnapshotInstructions)必须保留在包内。
如何通过定制 Flutter 引擎来进一步减小 iOS 包体积?
可进行编译优化和引擎裁剪:将编译参数从 -Os 改为 -Oz 可减小约 700KB;裁剪 Skia 可减少约 200KB;移除 BoringSSL(当使用客户端代理请求时)可减少约 500KB。需要 fork 引擎源码,修改依赖后重新编译。
Android 端 Flutter 减包方案与 iOS 有什么不同?
Android 端没有审核限制,可以完全动态下发所有 Flutter 产物(libapp.so、libflutter.so、flutter_assets 等)。只需将这些文件发布到云端,并定制 FlutterLoader.java 加载逻辑即可,无需像 iOS 那样保留指令段。
经过减包优化后,Flutter 应用在 iOS 和 Android 上的体积分别减少了多少?
iOS 端安装体积(Install Size)从 18.7MB 降至 11.8MB;Android 端可完全减去约 6.2MB 的 Flutter 产物体积。