ARTICLE · 1043358
入职第一周把 App 体积砍掉 40%,他只动了 5 个地方
这里每天分享一个 iOS 的新知识,快来关注我吧
前言
前段时间看了一篇讲 App 包体积的博客,作者拿 Granola 练手,安装体积从 80.9 MB 降到 58.8 MB,下载体积从 48.4 MB 降到 28.1 MB,一共花了三个半小时。
他用的是一个免费工具,在浏览器里就能跑,这篇博客里的做法我挑几个能直接照抄的记一下。
先分清两个数字
App Store 商品页上那个「大小」是下载体积,也就是装这个 App 最少要下多少数据,装完之后真正占你地方的那个数在手机上看,「设置 → 通用 → iPhone 储存空间」里那个才是安装体积。
两个数经常差一倍,Granola 优化完之后,安装体积少了 27%,下载体积少了 42%,同一个包,两个数掉的比例都不一样。
想在电脑上看得细一点,打开 Xcode 的 Organizer,挑一个 Archive 点 Distribute,右边有个 App Thinning Size Report,按机型一行一行列出来。
工具
工具叫 OpenBundle,免费的,可以网上搜一下,把 ipa 或者 zip 拖进网页就能分析,它整个跑在浏览器里,文件不上传也不会存下来,这点我挺喜欢。
打开之后先是一张树状图,方块面积就是体积,点进去能一层层看,每个文件的路径、压缩前后体积、SHA-256 都会记下来。
Mach-O 会真解析一遍,segments、sections、符号表、load commands、dyld export trie、链接了哪些库、代码签名、entitlements 都在里面,asset catalog 也拆开看,资源名、尺寸、scale、编码都有。
左边还有几页,Recommendations、Images、Binaries、Locales,最后一页 Compare,拿来比前后两个版本。这个工具怎么实现的就不展开了,感兴趣的同学可以自己去看。

重复的文件
Granola 的树状图里有一片红,红色表示这个文件和别处完全一样。
主 App 里有个 Assets.car 6.44 MB,Widget 里还有一份 2.46 MB,PhoneCalls 扩展里也有一份 7.38 MB,同一份图集拷了三遍。
再往下看,brand-background-texture 在 Widget 里 1.27 MB,在另一个扩展里 1.12 MB,两个文件一模一样。
工具一共找出 29 组完全相同的文件,加起来 13.0 MB。
这种问题一般都是在配置里出的问题,每个 target 都往自己的 bundle 里塞一份共享资源,没人拦着,把共用的图集挪到共享 framework 或者共享 asset catalog 里,扩展只留自己的图,改完 Assets.car 从 14.5 MB 掉到 6.69 MB。

图片
Granola 的建议列表里排第一的是图片,估出来 18.8 MB,比重复文件还多。
要查的地方就几个,有没有一张全屏背景图塞了 4000 px 宽,1x、2x、3x 是不是都留着,能用矢量的图标有没有用位图,照片走没走 HEIC,PNG 导出之前压过没有,pngquant、oxipng 跑一遍不亏。
哪些图最大不用猜,Images 页会直接列出来,压缩前后各多少也写着。
符号
Tesla 的包里排在建议最前面的是两条跟符号有关的,去掉符号元数据 14.5 MB,strip 掉符号 9.36 MB,比图片还多。
符号元数据和 dyld export trie 都塞在 __LINKEDIT 里,Release 包里大部分其实用不上,动手的地方就在 Xcode 的 Build Setting 里,改这么几个:
不需要对外导出的可执行文件,还能加 -Xlinker -no_exported_symbols。
不过有件事得先说清楚,dSYM 还是要照旧的生成、照旧的归档,剥离只动了 App 里那份二进制,线上崩溃日志的符号化还得靠 dSYM,改完了先拿一条真实崩溃日志试一下,别急着发版。
动态库和编译选项
Granola 的 Plugins 从 9.24 MB 降到 2.43 MB,截图里能看到 TwilioVoice 8.27 MB、Amplitude 1.10 MB、MarkdownUI 1.05 MB,主二进制和扩展各带一套。
动态库不是白来的,每个 dylib 都有头部,页对齐还要留填充,启动的时候 dyld 挨个加载,不需要动态加载也不给多进程共享的,静态链接就行,SwiftPM 默认就是静态。
编译选项里还有个 SWIFT_OPTIMIZATION_LEVEL,Release 从 -O 改成 -Osize,体积会小一点,性能损失一般感觉不出来。
改完之后
同一个包重新跑一遍,Assets.car 14.5 MB 到 6.69 MB,Plugins 9.24 MB 到 2.43 MB,设备上就是开头那两个数。

别让它涨回去
包体积不知不觉的涨回来是常态,可以加一个 CI 检查,每次发版跟上一版比,涨多了就别让它合进去,OpenBundle 能导出报告也能导入,两个版本对着看就知道哪个目录胖了。
除了看自己,还能拿它看别人,从 App Store 把竞品的 ipa 拉下来,Apple Configurator 或者 ipatool 都行,直接拖进去,Tesla 那个包里 Binary sections 有 273 MB,Watch App 112 MB,Frameworks 108 MB,我一般先看这种大块头,比抠自己那几百 KB 有意思多了。

最后
你上一次看自己 App 的包体积是什么时候?评论区聊聊~
这里每天分享一个 iOS 的新知识,快来关注我吧