前言:最近在了解 APP性能優化相關的一些知識,其中很重要的一個點就是包大小的優化,在做優化之前,我們需要搞清楚用戶在 App Store上看到的包的大小是什么?
1. 用戶眼中的App大小
以微信為例,我們可以直接在 App Store中打開微信App 的詳情頁,在【信息】模塊中,可以查看App的大小,如下圖:
而作為開發者的我們,在App 的某個版本上線之前,可以通過蘋果的 App Store Connect
后臺查看安裝包大小的功能:
選擇APP -> 打開 "TestFlight" -> 點擊構建的版本 -> 點擊頂部的"構建版本元數據
" -> 在"綜合信息
"下點擊"App Store 文件大小
",會展示出不同變體版本的大小,如下圖所示:
在上圖中可以清楚的看到不同變體版本的大小,而且區分了安裝大小和下載大小:
安裝大小:
是指App 在設備上安裝后占用磁盤空間的大小,用戶在 App Store中用戶看到的大小就是安裝大小
下載大小:
是指對 App 進行下載的壓縮大小
2. .app文件&.ipa文件
我們在發布應用時,最后提交的是一個 .ipa
文件,其實它就是一個 zip 壓縮包,我們可以使用unzip
命令,直接解壓就可以得到一個.app
文件,這個.app
文件其實就是個文件夾,里面包含了二進制文件和資源文件等等:
demo@MacBook-Pro ~ % file MonkeyDemo.app
MonkeyDemo.app: directory
所以.ipa
文件和.app
文件的關系:.ipa
文件其實就是.app
文件壓縮后的產物。
可以說明用戶下載的是.ipa
文件,下載完成之后解壓為.app
文件,下載大小是.ipa
文件的大小,導入大小是.ipa
解壓后得到.app
文件的大小。
但是我們通過某種方式從 AppStore 下載的.ipa
解壓后得到的.app
文件的大小和我們直接導出的.ipa
解壓后得到的.app
文件大小是有區別的,這個區別其實是蘋果會對已經通過審核的 App進行DRM
加密并重新壓縮,這個會影響到二進制文件的壓縮,所以 AppStore 顯示的二進制文件大小可能會比上傳到 App Store Connect的二進制文件更大,如下圖:
另一方面,蘋果在 iOS 9 推出了App Thining
,會影響我們導出 ipa 的大小,我們先來了解一下。
3. App Thinning
具體的可以參考:App Thinning官方文檔,這里簡單了解一下。
App Thinning
可以翻譯成應用瘦身,指的是App Store
和操作系統在安裝 app 的時候,會通過一系列的優化,減少安裝包的大小,而這一系列的優化,包括了三個過程:slicing
、bitcode
和 on-demand resources
。
3.1 slicing
這一步其實就是應用裁減,針對于不同的設備,它們可能需要ipa 中的不同的獨立資源,所以 App Store會針對不同的設備制作不同的"簡化版"的 ipa,也就是常說的"變體",這個簡化版的 ipa 值包含目標設備和操作系統版本所需的可執行架構和資源。
比如我們的圖片資源大都放在 Assets.xcassets
中,其中包含 @1x @2x @3x 的圖片,但是我們 iPhone 5S手機只需要@2x 的圖片,這一步做的就是幫我們去除 @1x @3x的圖片,也就是說,當用戶下載 App 的時候,蘋果會根據當前機型生成一套最適合這個機型的一套圖片,這樣就節省了大量的不必要的圖片資源,節省出來很大一部分空間。
還有就是我們導出的ipa
中的可執行文件,一般是含有多個 CPU 架構的:armv7
和arm64
,現在的iPhone一般都是需要 arm64
的,在這一步中蘋果就會把armv7
架構干掉。
從這一點來看在
VALID ARCHS
中干掉armv7
架構,對于包大小的優化來說沒啥用了,蘋果已經幫開發者做了這一步了。
從蘋果介紹App Slicing
時的這張圖中也可以看出來。
3.2 BitCode
Bitcode
是一個編譯好的程序的中間表示形式,開啟BitCode
,也就是說當未來有新的iPhone使用了新的 CPU 架構時,允許蘋果可以重新優化可執行文件,對可執行文件重新編譯和鏈接,不用我們重新提交 App了。
3.3 On-Demand Resources (iOS)
ODR
(on-demand resources
隨需應變資源)是iOS減少應用資源消耗的另外一種方法。比如多級游戲,用戶需要的通常都是他們當前的級數以及下一級的資源。ODR意味著用戶可以下載他們需要的幾級游戲資源。隨著你的級數不斷增加,應用再下載其他級數的資源,并將用戶成功過關的級數刪掉。
4. 自己導出的 ipa 和從 AppStore 下載的 ipa 對比
4.1 自己導出的 ipa 驗證
我們自己導出的 AppStore
正式包是沒有經過 App Slicing
的,比如可執行文件中含有多個CPU 架構,可以使用file
命令查看,如下:
2021-02-28 09-54-58 % file TestApp
TestApp: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O executable arm_v7] [arm64]
TestApp (for architecture armv7): Mach-O executable arm_v7
TestApp (for architecture arm64): Mach-O 64-bit executable arm64
使用otool
命令驗證是否加殼:
otool -l 可執行文件路徑 | grep crypt
2021-02-28 09-54-58 % otool -l TestApp | grep crypt
cryptoff 16384
cryptsize 901120
cryptid 0
cryptoff 16384
cryptsize 999424
cryptid 0
可以看到cryptid
值為0
,說明兩種架構下都沒有加殼。
在導出Ad Hoc
類型的ipa
時,是可以選擇導出指定設備所需要的包的,這需要我們在導出時修改配置,導出iPhone 7 Plus
的包,如下:
導出之后會包含一個 Apps 文件夾,里邊有多個 ipa:
可以通過App Thinning Size Report.txt
文件,查看Apps 文件夾中不同 ipa 的信息:
這里為什么有多個,我也不清楚,但是在上面文件中可以看到不同的ipa分別有自己支持安裝的設備(Supported variant descriptors
)。
我們解壓一個ipa
,再次用file
命令查看,可執行文件只包含一個 arm64
架構了。
5. 總結
通過上面的驗證,我們可以知道用戶在App Store
上看到的包的大小,其實就是.app
文件的二進制部分加殼之后,再經過 app slicing
的大小。
了解這個有助于我們對于ipa大小優化的操作進行數值化,驗證我們的操作是否有用。