夜雨聆风学习资料网

ARTICLE · 1043358

入职第一周把 App 体积砍掉 40%,他只动了 5 个地方

入职第一周把 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 导出之前压过没有,pngquantoxipng 跑一遍不亏。

哪些图最大不用猜,Images 页会直接列出来,压缩前后各多少也写着。

符号

Tesla 的包里排在建议最前面的是两条跟符号有关的,去掉符号元数据 14.5 MB,strip 掉符号 9.36 MB,比图片还多。

符号元数据和 dyld export trie 都塞在 __LINKEDIT 里,Release 包里大部分其实用不上,动手的地方就在 Xcode 的 Build Setting 里,改这么几个:

DEPLOYMENT_POSTPROCESSING = YES
STRIP_INSTALLED_PRODUCT  = YES
STRIP_STYLE              = all          # 保守一点用 non-global
OTHER_LDFLAGS            = -Xlinker -S  # 去掉调试符号

不需要对外导出的可执行文件,还能加 -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 的新知识,快来关注我吧

相关学习资料