在做安裝包大小優(yōu)化前埋同,我們應該首先搞清楚州叠,用戶在 app store 上看到的包大小,究竟是什么凶赁?
如果我們衡量安裝包大小的口徑咧栗,和用戶看到的大小不一致,那么做優(yōu)化時的優(yōu)先級和ROI衡量就可能跑偏虱肄,甚至出現(xiàn)優(yōu)化效果為負的悲慘結局致板。
首先拋出結論:用戶在 app store 上看到的包大小,是:
- .app 文件
- 的二進制部分被加殼后
- 再經過 app slicing
的大小咏窿。
如何查看
在某個版本的 app 上線之前斟或,開發(fā)者應該如何知曉它在用戶眼中的大小呢?
蘋果的 itunes connect 后臺為開發(fā)者提供了查看安裝包大小的功能集嵌。
在 itunes connect 后臺萝挤,開發(fā)者可以看到當前版本針對不同機型的大小。
這里的大小分為兩個口徑:
Download Size 和 Install Size根欧。
根據網頁上的說明:
Install Size 是這個 app 安裝后怜珍,會占用的磁盤大小凤粗;
Download Size 是 app 經過壓縮后的大小绘面。
根據經驗,用戶在 app store 上看到的大小侈沪,就是 itunes connect 后臺中顯示的 Install Size揭璃。
而令開發(fā)者在意的,“超過 150 MB 的 app 必須連接至無線局域網才能下載”的規(guī)則中的 150 MB亭罪,指的其實是 Download Size瘦馍。
幾個口徑
Download Size 和 Install Size 是如何計算出來的,我們等下再說应役。
拋開 itunes connect 和 app store情组,平時我們在開發(fā)打包一個 app 時燥筷,經常會接觸到這樣幾個安裝包概念:
- ipa
- app
ipa 可能是我們最熟悉的“安裝包”的格式。通過 Xcode 的 archive 方式院崇,最終打出的安裝包的格式就是 ipa肆氓。
實際上,ipa 就是一個 zip 壓縮包底瓣。我們可以用 unzip 的方式來解壓一個 ipa 文件谢揪。
這樣,我們會得到一個后綴名為.app的文件捐凭。
甚至可以想進入一個文件夾一樣進入到這個.app中拨扶,窺探二進制、各個資源分別占據了多少大小茁肠。
這里我們知道了患民,.app 文件和 .ipa 文件的關系:
ipa 文件是 app 文件 zip 壓縮后的產物。
用戶看到的大小
那么用戶看到的 Install Size垦梆,究竟是 .app 文件的大小匹颤,還是 .ipa 文件的大小呢?
答案:都不是托猩。但是 .app 文件的大小與 Install Size 的口徑更為接近惋嚎。
加殼
蘋果在 iOS 9 推出了能減小安裝包的 app thining 功能。我們先不考慮這個功能站刑,看看 iOS 9 以前 Install Size 與 .app 文件的關系。
要獲取 app store 上的安裝包鼻百,其實沒有正規(guī)的做法绞旅。有一個比較trick的技巧可以獲得:
http://www.reibang.com/p/ce018473fad0
通過這個方式,我們可以下載到一個 .ipa 文件温艇。
這個 ipa 文件經解壓后得到的 app 文件因悲,其大小與 iOS 9 以下設備在 app store 上看到的大小是吻合的。也與 itunes connect 中勺爱,開發(fā)者看到的 Install Size 是吻合的晃琳。
但是,它與開發(fā)者提交到 itunes connect 前的 app 文件大小琐鲁,是有一定差距的卫旱。
比如,我們提交到 app store 上的 ipa 解壓后的大小為 297.1MB
從 app store 上下載的 ipa 解壓后大小為 301.9MB
其中這 3.8 MB 的大小差異來自哪里呢围段?
來自加殼顾翼。
我們對比了這兩個 app 包中的各個文件大小,發(fā)現(xiàn)各資源文件的大小完全一致奈泪,只有二進制文件的大小發(fā)生了改變适贸。
使用 otool 命令
otool -l 可執(zhí)行文件路徑 | grep crypt
我們可以驗證灸芳,app store 中下載的包經過了加殼,而提交 itunes connect 前的包沒有拜姿。
使用
otool -l
命令可以輸出 Mach-O 文件加載的 load command烙样。經對比發(fā)現(xiàn),雖然加殼改變了TEXT段的內容蕊肥,卻沒有改變TEXT段的大小谒获。這 3.8 MB 的大小差異主要來自 __LINKEDIT 和 LC_CODE_SIGNATURE 這兩個段,這兩個段都與動態(tài)鏈接器有關晴埂。
因此究反,我們可以得到結論:iOS 9 之前,用戶看到的 Install Size 的大小儒洛,是 .app 文件經過加殼的大小精耐,粗略的可以認為就是 .app 文件的大小。
app slicing
上述的分析針對于 iOS 9 以下設備看到的情況琅锻。
如果考慮蘋果在 iOS 9 上推出的 app thining 功能卦停,安裝包大小會有什么影響呢?
我們先了解一下恼蓬,如果沒有 app thining惊完,一個安裝包中會包含哪些內容。
對二進制來說处硬,由于一個安裝包需要同時支持 iPhone 5 等 32 位設備和 iPhone 5s 以上的 64 位設備小槐,所以二進制中需要包含 armv7 和 arm64 兩個架構的 Mach-O 文件。
對于放在 asset catalog 中的資源來說荷辕,一般來說凿跳,開發(fā)者為了更好的適配 iPhone 6 等 2x 屏幕的設備和 iPhone 6 plus 等 3x 屏幕的設備,每一個圖片資源會引入 2x 和 3x 兩個版本疮方。
對于其他圖片/資源來說控嗜,它們也會被收入到安裝包中。
這里骡显,我們可以明顯發(fā)現(xiàn)疆栏,如果一個設備下載安裝了安裝包中的全部內容,有兩個明顯浪費的地方:
- 有一份它不需要的 Mach-O
- 有一份它不需要的資源圖
蘋果在 iOS 9 推出的 app slicing惫谤,就幫助開發(fā)者將這兩個浪費的地方干掉了壁顶。
對于資源圖,官方文檔中有說明:
A thinned .ipa is a compressed app bundle that contains only the resources needed to run the app on a specific device.
https://developer.apple.com/library/archive/qa/qa1795/_index.html
對于二進制溜歪,我們沒有在官方文檔中找到說明博助。但 WWDC App Thinning in Xcode 一篇中這樣介紹了 app slicing 功能:
這張圖中體現(xiàn)了,無論是二進制還是 asset catalog 中的資源痹愚,app slicing 都只保留了當前設備所需的部分富岳。
而在導出 ipa 時蛔糯,在配置 plist 文件中加入 <thin-for-all-variants> 選項,則可以導出針對不同機型的 ipa 文件窖式。經實驗蚁飒,這些 ipa 文件解壓后得到的 app 文件大小,與 itunes connect 后臺各個設備對應的 Install Size 是吻合的萝喘。
優(yōu)化建議
正如文章開頭的結論:
用戶在 app store 上看到的包大小淮逻,是:
- .app 文件
- 的二進制部分被加殼后
- 再經過 app slicing
的大小。
得知了用戶看到的包大小究竟是什么含義阁簸,我們可以避開一些包大小優(yōu)化的坑爬早。
比如,由于 app slicing 的存在启妹,圖標應該盡可能用 asset catalog 管理起來筛严。所以試圖用 webp 等格式來替代 asset catalog,可能是負向收益饶米。
(這個思路經過實驗桨啃,結論是,在我們的業(yè)務場景下檬输,如果用 webp 替代 asset catalog照瘾,對于 2x 設備的 Download Size 是負向收益,因為 2x 設備不得不使用 3x 的圖片丧慈,并且 webp 圖的壓縮率比 asset catalog 低很多)
再比如析命,不要幻想拋棄 armv7 架構的設備,可以減小包大小逃默。蘋果已經幫開發(fā)者做過這一步了鹃愤。