iOS 缩小 ipa 大小

一、爱奇艺

爱奇艺移动应用优化之路:如何让崩溃率小于千分之二

  1. iOS8 对于 App 的 text 段有 60MB 的限制;
  2. 超过 200MB 的 App 需要连接 WIFI 下载(之前是 150MB)
  3. 过大会导致启动慢,rebase/binding 时间长
  4. 除去商店中 App 的简介、截图,很多用户都会关注 App 的大小,尤其是使用空间为 8G、16G 的用户

安装包大小的优化,主要包含两大块:资源大小的优化和二进制大小的优化。

资源大小的优化相对来说比较简单,主要包括以下几个方面:

  1. 资源压缩
  2. 未使用、重复资源的删除
  3. 资源上云

1.1 资源压缩

Xcode 的编译选项中,提供了 Compress PNG FilesRemove Text MetaData From PNG Files

但是由于 PNG 是无损压缩,经过 Xcode 压缩后的图片资源,依然很大。

那么 PNG 是否可以通过“有损”压缩,来缩小体积呢?答案是可以。通常 UI 同事出的图都是 32 位图片, 32 位图相当于 Alpha 透明度 + 24 位图,总共可以显示 224 = 16777216 种颜色。图片颜色丰富固然好,但是一般情况下,APP 包中的图片色彩范围实际很小,按钮或者一些小图使用 8 位图肉眼完全看不出与 32 位图有什么区别。

因此团队使用 pngquant 对大多数的 32 位图进行了处理,将其转为 8 位图,并且使用 Zopfli 进行了压缩,这样整体的 PNG 图片资源大概被压缩了 70% 左右。这里要注意,由于一些渐变背景的颜色覆盖范围较大,转为 8 位图颜色丢失较大,表现效果会差很多,所以这些图片要谨慎处理。

1.2 未使用、重复资源的删除

随着版本迭代,一些功能可能会下线,有时相关的资源却没有及时删掉,有些功能由于开发者不同,可能部分相对通用的图片会有重复。这部分资源会随着时间的推移慢慢累积,及时发现并删除是非常必要的。

图片是否被使用,可以通过图片名字符串的匹配来判断。需要注意的是图片名拼接的情况(比如新手引导的功能,很容易出现图片名拼接数字的情况),在图片资源预处理的过程中,通常有两张以上图片有相同的前缀或后缀,可以将其相同的部分提取出来,作为字符串匹配的依据。

重复资源的情况一般会发生在一些按钮、或者背景图由同一个 UI 同事生成,发给了不同功能的开发人员。这部分图片的判定一般可以通过图片大小相同或相近(大小在 5% 范围内)、分辨率相同进行初筛,然后再通过 magick compare 工具进行图片的对比,提取出相似度极大的即可。

最后工具输出的结果需要开发人员进行二次确认,确保不会有误删的情况出现。


1.3 资源上云

资源上云可以有效减少包内资源,唯一要注意的是这些资源由于是 lazy load,所以比较适合层级较深的页面使用。图片逻辑可以封装为工具类,前端使用只是调用一个方法,具体哪些图片取本地、哪些图片走云的策略可以自由配置。此外,资源上云的另一个好处是可以很方便地实现动态换肤。


JS、表情库等资源可以通过打包预下载的形式,并增加更新策略,这样 RN 页面、WebView、表情库都不占用安装包大小。

二进制大小的优化相对来说比较困难,除去部分功能使用 Web 页面或者 RN,主要工作集中在无用类、无用代码的分析及删除。

Xcode 可以生成一个 Link Map 文件,文件包含了可执行文件的路径、目标文件、符号等各种信息。文件中 __objc_classrefs 表示引用到的类,_objc_classname 表示 App 内的类名,通过分析两者的差别,可以得出未使用的类,同理,分析 __objc_selrefs 和 _objc_methname 的差别可以得出未使用的方法。但是由于 OC 的动态性,得出的结果会有大量误报的情况。那么如何减少误报呢?可以通过测试 case 的代码覆盖率,来提高无用代码精确度的分析。

Xcode 设置中开启代码覆盖率后,编译时会生成 gcno 文件,程序运行时会产生 gcda 文件,通过 lcov 解析即可得到代码测试覆盖率。如果开发阶段开发人员的自测,以及全功能 case 跑完,都有一些类或方法没有被覆盖到,并且这些类或方法又跟 Link Map 文件分析的结果一致,那么这些类或方法会被标记为无用代码,由工具统一收集并指派给相关开发人员进行处理。

二、其他处理

  1. 配置编译选项 Generate Debug Symbols 设置为 NO;

  2. 舍弃架构,如:armv7,根据实际选择。

  3. 编译的版本必须是 release 版本,

  4. 查找内部使用到的第三方库,一方面可以进行删减代码,用不到的类,直接删除,还有第三方库中的图片资源统统删除掉,如果能够自己手写实现的,那费功夫自己写吧

  5. 图片

    • 压缩图片

      不重要的图片可适当采用 8bit png 图片

      矢量图:由计算机的算法产生的,可以无限放大或缩小,不会有任何损失,通常由矢量软件制作。

      位图:由一个一个的小色块组成,放大后会看到那些小色块,同一面积内小色块越多,分辨率就越高。

      矢量图优点:

      • 可以无限放大或缩小,不会影响图像素质;
      • 文件体积较小,编辑灵活

      缺点:

      • 表达的色彩层次不清,整体观感效果不如位图

      位图优点:

      • 能很细腻地表达图片的效果,图片表达效果非常好

      缺点:

      • 不能放太大,减少文件分辨率后会影响图片质量
      • 图片占据空间较大

      一些对图片要求高的用位图,如:照片。其他的尽量用矢量图,如:文字、表格、卡通图片等

    • 去掉无用的图片

      • 用代码绘制简单的纯色图片 用 Sketch 和 PaintCode 快速得到绘制代码。
      • 如果不需要使用透明,可以用 jpeg 代替 png。jpeg 减少了些效率但更加小。需权衡性能,大小。
      • 对 32 位的图片,尽可能的使用高压缩率,使用 PS 的“Save For Web”功能,可以有效的减小 JPEG 和 PNG 图片的尺寸。 默认情况下,在 build 时,PNG 图像就被 pngcrush 压缩。
  6. 音频

    压缩音频,尽可能使用 AAC 或者 MP3 格式,并且使用一个较低的码率。通常 44.1khz 的码率有点浪费,降低一定的码率也不会丢失多少音质。

  7. 视频

    视频也可以使用类似于音频的处理方法,音视频的压缩可以很大程度的压缩,但是要注意压缩的格式,是不是会增加编解码的负担,这要权衡考虑。

  8. Assets

    检查 bundle 中的无用文件,不要打包到 app 或者静态库中。可以点击文件,在右侧的 file inspector 里面的 target membership 中取消勾选;或者在 build phase 里面的 Copy Bundle Resources 中去掉。

    确定 dead code(代码被定义但从未被调用)被剥离,Build Settings 里 DEAD_CODE_STRIPPING = YES。去掉冗余的代码,即使一点冗余代码,编译后体积也是很可观的。

posted @ 2020-02-26 13:42  和风细羽  阅读(753)  评论(0编辑  收藏  举报