简介
Flutter 包体积优化应从 release 包的构成开始。页面懒加载、FutureBuilder 和 ImageCache 主要影响运行时行为;除非它们改变最终打包资源或可达代码,否则不能直接当作安装包体积优化。
1. 先生成 release size report
Android 可以生成 App Bundle 或 APK 的 size analysis 文件:
flutter build appbundle --release --analyze-size
flutter build apk --release --analyze-size
size analysis 文件可在 DevTools App Size 工具中查看 Dart AOT 代码、Flutter/native 库、资源和依赖包的构成。debug 包含调试信息和开发开销,不适合代表用户下载的 release 包。
AAB 上传包大小也不等于某台设备的实际下载大小;Google Play 会按设备配置生成对应的拆分包。iOS 的 App Store 下载大小同样受 App Thinning 和目标设备影响,应查看 Apple 的 App Size Report。
2. 根据报告检查主要构成
Dart 代码与依赖
Dart AOT 构建会移除不可达代码。删除未使用依赖、避免不必要的平台包,并用 size report 验证实际变化;仅把 import 改成 show/hide 不会自动带来额外收益,因为编译器本身已有 tree shaking。
图片、其他资源与字体
- 删除不再引用的原图、重复资源和调试素材。
- 按实际用途压缩图片,并检查是否把超大源图作为 asset 打进安装包。
- 只打包应用需要的字体文件和字重;不要在没有测量时假定字体一定是最大项。
- 图片缓存尺寸影响运行时解码内存,不会改变已经打包进去的原始 asset 大小。
原生库与 ABI
size report 中如果 native library 占比高,逐项核对第三方 SDK、重复架构和原生插件。Play Store 会对 AAB 按设备筛选 ABI;单独发布 APK 时,—split-per-abi 会生成不同架构 APK,它不会让同一个 APK 对所有设备都变小。
3. 分析符号与混淆
可以在 release 构建中拆分调试符号:
flutter build appbundle --release --obfuscate --split-debug-info=build/symbols
保存与每个发布版本严格对应的符号文件,否则线上堆栈将难以还原。混淆主要用于符号处理与代码保护;不要把它描述成稳定、固定比例的包体积缩减手段。优化前后都应保留 size analysis 文件做对比。
4. 不要把运行时优化混进包体积
这些做法可以解决其他问题,但本身不等于减小安装包:
- 路由懒加载和页面按需创建:主要改变启动与运行时行为。
- FutureBuilder:用于呈现异步状态,不会自动从 AOT 包中剔除代码。
- 图片缓存管理器:影响运行期间的缓存策略。
- FlutterImageCompress:只有当它将最终被打包的图片资源转换为更小资源时,才可能减少 asset 体积;在运行时压缩用户选中的图片不是安装包优化。
5. 用同一构建条件比较
对比时保持 Flutter commit、构建模式、目标 ABI、资源和签名配置一致。记录分析文件与发行包,并按报告中真正占比较高的模块逐项优化;商店展示的下载大小仍以商店针对设备生成的结果为准。
实战记录
我尚未为自己的应用保留一组可复现的优化前后 size report,因此本文不提供体积下降百分比或“最大资源”结论。后续记录应包含目标平台、设备/ABI、Flutter commit、构建命令、报告文件和前后差异。
