货拉拉 iOS 包大小优化探索与实践

一. 背景介绍

曩昔几年,货拉拉事务高速开展,作为中心事务进口的用户端App,在事务与技术上也在与时俱进不断晋级迭代,以满足用户多样化的需求,随之而来也遇到了移动端开发同学都会遇到的问题:App需求“减肥”了,站在用户的视点,以下几个目标是比较简单被感知到的:

  1. 安装包巨细
  2. 发动速度
  3. 稳定性
  4. 耗费
  5. 流畅度

包巨细含义特殊,它是App重要的根底体会目标之一,用户要安装App首先要面临的是App的包巨细,它影响着用户的安装率,安装成功率,卸载率,在2019谷歌开发者大会上,谷歌给出了一个很具体的数据,包体巨细每上升6MB,运用下载转化率就会下降1%,不同区域转化率略有差异,每削减10MB ,全球均匀下载转化率会进步1.75%。

本文将为咱们介绍货拉拉用户端在优化安装包巨细方向做的一些探究与尝试,期望能给咱们在自家App包巨细优化方面供给一些学习和思路。

  1. 包巨细概念

App包巨细能够了解成安装包(即.app文件)巨细或许下载包(即.ipa文件)巨细,两者的关系是,下载包(即:ipa文件)是用户从App Store商店下载时的紧缩包巨细,要查看该数据需求在App Connect后台进行查看,当紧缩包下载完结后会主动解压,安装到用户的手机上,安装结束后就变成安装包(即.app文件),占用用户手机的磁盘空间;

一般而言,安装包(即.app文件)会比下载包(即.ipa文件)大很多,安装包巨细优化后,下载包自然会相对减小,这儿咱们将安装包作为本次讨论的技术目标。

  1. 注重包巨细

一款App在迭代的进程中,跟着新需求的不断丰富,势必会形成包体积逐步增大,App前期因为功用比较简单,而且优化空间有限,用户感知并不明显,包巨细或许不受注重,但跟着App功用不断丰富和多元化,包巨细自然水涨船高,当大到必定值后,则会在一些方面发生消极影响:

  1. App Store OTA 下载巨细约束:

苹果公司为了防止用户的运营商流量超限,约束了用户直接经过运营商流量从 AppStore 下载 App 的最大巨细,这将必定程度上影响新用户转化以及老用户的用户体会和晋级率,该约束巨细历年都会做出必定的调整 :

由2017年9月的 100M 到2019年5月的 150M,iOS13体系发布之后,iOS13 及以上用户能够运用流量下载超出 200MB 的 App, 但需求用户「设置」挑选战略「超越 200MB 恳求许可」,但iOS13 体系以下用户仍然无法流量下载。

  1. App __TEXT 段巨细约束:

除了以上约束,苹果公司对App的可履行文件(即Mach-O文件)的__TEXT段巨细也做了严厉约束要求,超出这个约束将无法经过App Store的审阅:

  1. iOS 7 之前,二进制文件中一切的 __TEXT 段总和不得超越 80 MB;
  2. iOS 7.x 至 iOS 8.x,二进制文件中每个特定CPU架构的 __TEXT 段不得超越 60 MB;
  3. iOS 9.0 之后,二进制文件中一切的 __TEXT 段总和不得超越 500 MB。
  1. App功能问题

App包巨细的劣性添加,首要原因有较多冗余的代码文件,资源文件(如图片,字体文件,db文件等)以及低效的代码逻辑,这些因素不只影响包巨细,还涉及App的其他功能目标,如发动时长,流畅度(FPS),Crash率,乃至事务的深层次迭代功率;

二. 苹果为咱们做了哪些

  1. App Thinning

App Thinning 苹果公司推出的一项能够改善 App 下载进程的新技术,首要是为了处理用户下载 App 耗费过高流量的问题 ,它能够让 App Store 和操作体系在安装、更新及运转 iOS 或许 watchOS 的 App 等场景时,经过一系列的优化,尽或许削减安装包的巨细,仅下载所需的资源,削减 App 的占用空间,然后节省设备的存储空间。

App Thinning 有三种办法,包括:App SlicingBitcodeOn-Demand Resources

  1. App Slicing,很多运用需求在不同尺度的设备上运转,针对这些不同的设备,它们内含不同的独立资源,而大部分是你的设备不需求的,App store会针对不同的设备创立不同的变体,适用到不同的设备。

货拉拉 iOS 包大小优化探索与实践

需求留意,图片资源有必要供给多分辨率的图片选用Asset Catalog办理,才能在Slicing中发挥作用。

  1. On-Demand Resources,按需加载资源,在下载App的时分,App中包括的不重要资源先不下载,比及需求时,再由体系向苹果的服务器Server发送恳求,下载指定的资源包,以削减初装 App 的包巨细,首要用在游戏多关卡场景,玩家解锁游戏的特定关卡后,能够下载新关卡及这个关卡相关的特定资源。此外,玩家现现已过的关卡能够被移除以便节约设备上的存储空间。
  2. Bitcode,一个编译好的程序的中心表示办法,App敞开Bitcode,传到 iTunes Connect后会在 App Store中进行链接和编译,生成一个中心表现办法(Bitcode),再将这个Bitcode编译为可履行的64位或32位程序,若后续苹果新增一种CPU架构,那么苹果可从头优化咱们程序的二进制文件以进行适配,而不需咱们从头提交新版别到App Store上,此优化不明显(需求留意的是,运用Xcode14构建时包时,若敞开BitCode,苹果将约束提交到App Store)。

三. 咱们在包巨细上的探究

1. 分析安装包

安装包构成由以下三个部分:

  1. Mach-O可履行文件:首要包括项目的中心事务代码及静态库
  2. 资源文件:

图片资源:包括Assets.car,Bundle文件,GIF,JPG,PNG,JSON等文件

静态WEB资源:JS,CSS,HTML

视图资源:XIB,Storyboard

音视频资源:mp4,mp3,caf等

其他资源:签名文件,字体文件,PLIST文件,db文件,国际化资源文件等等

  1. Framework,运用程序依赖的动态库

货拉拉 iOS 包大小优化探索与实践

咱们从以上三个部分进行必定程度的优化,下图是咱们搜集的优化战略,有些需依赖其他部分的支撑,如资源动态化,需求后端或许运维的支撑,在施行中存在可行性及收益比两方面考虑,具体能否落地需看公司实际状况。

货拉拉 iOS 包大小优化探索与实践

2. 编译器优化

  1. 去掉无用架构

可经过Xcode的Excluded Architectures项添加需排除的CPU架构,常见的架构及机型搭配:

  • i386 架构,支撑32位模拟器,已不再运用;
  • x86_64 架构,支撑64位模拟器,现在都是64位的模拟器;
  • armv7, armv7s 架构,支撑32位真机,根本上筛选了;
  • arm64 架构,支撑64位真机,在iPhone5S开始支撑,苹果用户根本都是这个架构

能够在Xcode的Excluded Architectures装备项添加armv7,armv7s,让咱们构建的包只支撑arm64架构,尽管苹果有App Slicing机制也会做指定机型的切开,但此操作优化了咱们平时的编译时长和构建产物巨细;

  1. Optimization Level

  1. 选项None[-O0]:编译器不会优化代码,意味着更快的编译速度和更多的调试信息,默许在 Debug 办法下敞开;
  2. Fast[-O, O1]: 编译器会优化代码功能而且最小限度影响编译时刻,此选项在编译时会占用更多的内存;
  3. Faster[-O2]:编译器会敞开不依赖空间/时刻折衷一切优化选项。在此,编译器不会打开循环或许函数内联。此选项会添加编译时刻而且进步代码履行功率;
  4. Fastest[-O3]:编译器会敞开一切的优化选项来进步代码履行功率。此办法编译器会履行函数内联使生成的可履行文件变得更大。一般不引荐运用此办法;
  5. Fastest Smallest[-Os]:编译器会敞开除了会明显添加包巨细以外的一切优化选项。默许在 Release 办法下敞开;
  6. Fastest, Aggressive Optimization[-Ofast]:发动 -O3中的一切优化,或许会敞开一些违背言语标准的一些优化选项。一般不引荐运用此办法。
  1. Strip Link Product

Strip Link Product会受到Deployment Postprocessing设置的影响,只有当Deployment Postprocessing设置为YES时,该选项才会收效,当Strip Link Product为YES能够帮咱们优化掉Strip Style中设置的不需求的符号信息,但调试App时断点不会中止,App Crash后控制台也无法看到具体的类名和办法名,一般Debug办法设置为NO,Release办法设置YES。

Strip Style是咱们需求去除的符号的类型的选项,包括:

1)All Symbols: 去除一切符号,一般是在主工程中敞开;

2)Non-Global Symbols: 去除一些非大局的 Symbol(保存大局符号,Debug Symbols

相同会被去除),链接时会被重定向的那些符号不会被去除,此选项是静态库 / 动态库的主张选项;

3)Debug Symbols: 去除调试符号,去除之后将无法断点调试;

  1. Make Strings Read-Only

复用字符串字面量,削减不必要的生成,也是一种优化办法。

  1. Dead Code Stripping

消除无效代码,C/C++/Swift 等静态言语编译器会在 link 的时分移除未运用的代码,关于OC等动态言语是无效的。

  1. Link-Time Optimization

此设置有三个选项值:

1)默许No 不敞开链接期优化

2)Monolithic 生成单个 LTO 文件,每次链接从头生成,无缓存高内存耗费,参数LLVM_LTO=YES

3)Incremental 生成多个 LTO 文件,增量生成,低内存耗费,参数 LLVM_LTO=YES_THIN(引荐)

LTO带来的优化:

1)将一些函数內联化:不用进行调用函数前的压栈、调用函数后的出栈操作,进步运转功率与栈空间利用率;

2)去除了一些无用代码:假如一段代码分布在多个文件中,可是从来没有被运用,一般的 -O3 优化办法不能发现跨中心代码文件的剩余代码,因此是一个局部优化。可是 Link-Time Optimization能够在链接时发现跨中心代码文件的剩余代码;

3)对程序有大局的优化作用:这是一个相对广泛的概念。举个例子来说,假如一个 if 办法的某个分支永不或许履行,那么在终究生成的二进制文件中就不该该有这个分支的代码。

  1. Asset Catalog Compiler

此装备的Optimization含三个选项,空、time和space,挑选space能够优化包巨细。

3. 资源优化

  1. 删去无用资源

App包中的资源有:未运用图片(GIF,PNG,JPG,webp等),音视频,Plist文件等等,能够运用业界东西进行扫描,比方:

1)LSUnusedResources,一个可视化客户端东西,运用简单,不做赘述;

2)fdupes指令查找项目中的重复文件,原理是比照不同文件的签名,签名相同的文件就会判定为重复资源,此办法或许存在误判,主张人工复核后进行删去;

这儿分享一下咱们运用Shell脚本扫描未运用资源的逻辑,因为咱们的项目选用了组件化,每个组件的资源都是独立隔开的,所以扫描时需求每个组件单独扫码,逐个收拾,每个组件扫描后可得到:

1)承认未运用的资源途径(这儿包括GIF,PNG,JPG,Webp等类型文件),此类文件可直接删去;

2)或许未运用的资源途径,一般因文件名带有数字(或许字符串拼接的文件名),此类文件需再次承认

值得一提的是,选用脚本办法会比可视化东西更灵活:
1)可依据需求对脚本匹配的正则进行修改来支撑扫描识别出更多类型文件;
2)扫描的文件可输出文件途径,用于再次承认;
3)如项目选用的外部脚本的主动化构建打包,咱们的扫描脚本可移植到打包流程(一般用于优化外部三方库)中的资源文件;
4)可持续对脚本进行拓宽,将扫描的指定图片进行紧缩,这一点也能够嵌入到CI流程中

每次资源收拾后,迭代几个版别就会发现工程中又会发生很多无用资源,其间以图片资源居多,所以能够将资源优化这个才能作为优化惯例项,定时收拾,这一点咱们在后面防劣计划中会说到,咱们经过定时扫描收拾,截止现在咱们在收拾无用资源这一块的收益是6.73M,后续咱们会持续履行,确保项目项目的资源利用率。

咱们的脚本流程:

货拉拉 iOS 包大小优化探索与实践

经过find指令递归查找组件工程各目录,grep进行文件名匹配判别文件是否被运用,需求留意,因为咱们工程首要选用了OC,界说句柄时,资源引进办法只考虑@””和xib办法引进的资源文件(如图片),能够依据自身项目的图片引进规则对匹配句柄进行调整:

    // 以下为代码片段
    # 假如图片是在.imageset目录下,则不能用图片名判别,而是要用.imageset名,因为图片名或许与.imageset名不同,而代码中运用的却是.imageset名
    if [[ $png =~ ".imageset" ]];then
        v=`echo $png | grep -Eo "/Users(.*).imageset"`
        match_name=`basename $v | awk -F '.imageset' '{print $1}'`
    fi
    pic_size=`wc -c $png | awk '{print $1}'`
    referenced=false
    # 判别图片名称是否引用到
    if grep -q "$match_name" "$maybeImageSentencePath"; then
        referenced=true
    fi
    # 假如图片是带有数字的,就判别为或许是拼接的图片
    contaT=$(echo $match_name | grep "[0-9]")
    if [[ "$contaT" != "" ]];  then
        MaybeUnusedCount=`expr $MaybeUnusedCount + 1`
        echo "$png"  >> $maybeUnusedImageFilePath
        echo "${png}图片或许未用到"
        # 将运用到的图片,超越阀值写入文件
        if [ $pic_size -gt $k_base_size ];then
            echo "大于${k_base_size},写入文件"
            img_kb_size=`awk 'BEGIN{printf "%.2f\n",'$pic_size'/'$k'}'`
            echo "$png ${img_kb_size}KB" >> $mayUnusedExceedPicPath
        fi 
        continue
    fix
    # 图片不在赋值文本中
    if ! $referenced ; then
        UnusedCount=`expr $UnusedCount + 1`
        echo "$png"  >> $unusedImageFilePath
        echo "${png}图片未运用"
        TotalSize=`expr $TotalSize + $pic_size`
        # 将运用到的图片,超越阀值写入文件
        if [ $pic_size -gt $k_base_size ];then
            echo "大于${k_base_size},写入文件"
            img_kb_size=`awk 'BEGIN{printf "%.2f\n",'$pic_size'/'$k'}'`
            echo "$png ${img_kb_size}KB" >> $unusedExceedPicPath
        fi  
        continue
    fi
    # 图片用到了,在imageset目录下,有三张png图片,则需求去掉1x图片
    if [[ $png =~ ".imageset" ]];then
        path=`echo $png | grep -Eo "/Users(.*).imageset"`
        files=$(ls $path)
        count_flag=0
        for filename in $files
        do
            if [[ $filename =~ ".png" ]]; then 
                count_flag=`expr $count_flag + 1`
            fi 
            if [[ "$count_flag" == "3" ]];then 
                echo $png >> $usedContain3Pic
            fi 
        done 
    fi
done

这儿咱们还添加了经过扫描出超越某个阈值的图片,首要用于查看项目中的大图,大图的优化空间会更大;

 # 将运用到的图片,超越阀值写入文件
    if [ $pic_size -gt $k_base_size ];then
        echo "大于${k_base_size},写入文件"
        img_kb_size=`awk 'BEGIN{printf "%.2f\n",'$pic_size'/'$k'}'`
        echo "$png ${img_kb_size}KB" >> $exceedPicPath
    fi  

另外,第一次施行时会发现存在很多文件未运用,这儿能够分享一个简单的脚本,批量进行删去:

delete_path="项目途径"
# `rm -fr $delete_path;mkdir $delete_path`
# filePath="这儿填前面扫描后得到的资源途径集合的文本途径"
cat $delete_path | while read line
do  
    if [[ "$line" =~ ".imageset" ]];then 
        img_dir=`echo "$line" | grep -Eo "/Users(.*).imageset"`
        rm -fr $img_dir
    # else 
        # rm "$line"
    fi
    # cp $line $delete_path
done
  1. 图片紧缩

图片资源的最好用 Asset Catalog来进行办理,Xcode 构建进程中,在履行到compile asset catalog时,会利用构建Asset Catalog的actool插件会对Asset Catalog中的png图片进行解码,得到 Bitmap 数据,然后再运用actool的编码紧缩算法进行编码紧缩处理,假如放入到Assets中的是JPG图片,终究也会转成png图片存放到Assets.car中。

插件actool的紧缩算法有 lzfse,palette_img,deepmap2,deepmap_lzfse,zip。

需求留意的是,无损紧缩是改换图片的编码紧缩算法来削减巨细,并未改变像素数据,所以无损紧缩的图片不能优化Assets.car的终究巨细,但有损紧缩是能够,这儿阐明下咱们在图片紧缩方面做的几点探究。

常见的图片紧缩办法有:

  1. TinyPng,它是一个网页东西,有损紧缩,需求联网,不支撑批量处理;
  2. TingPNG4Mac,属于Mac的客户端东西,依据TinyPng完结的;
  3. ImageOptim,客户端东西,支撑无损紧缩和有损紧缩两种办法,可自界说紧缩办法;
  4. pngquant,指令行东西,有损紧缩,编写脚本批量紧缩,支撑自界说紧缩质量参数;
  5. Guetzli,针对数码图画和网页图画的JPEG编码器,支撑JPG图片的有损紧缩;

因为项目在迭代进程中运用到的图片在切图,选图上的忽略或许会将较大图片引进进来,所以咱们会定时扫描,查看项目中的大图是否合格,确保需求的图片是最优的,经此阶段,咱们在项目中图片资源紧缩的收益如下:

组件 收益巨细
主工程 1.8M
User子组件 4.72M
Common子组件 9.17M
搬家子组件 3M
地图组件 2.66M
IM组件 0.2M
其他三方库 0.3M

经过第一步的无用资源删去后,项目中存在的图片资源根本上是咱们必需的了,此时咱们依然选用Shell脚本对各组件的图片进行紧缩,经过调研咱们发现,pngquant东西是咱们需求的,咱们选用了pngquant指令来紧缩项目中的图片。

pngquant紧缩原理:将24位或32位的RGBA的PNG图转换成8位的PNG图,保存全部的alpha通道,生成的图片兼容一切现代web浏览器;

官方阐明:

货拉拉 iOS 包大小优化探索与实践

紧缩指令:

$ pngquant --quality=20-30 文件名

当quality设置在20-30时,第一次紧缩后,在不影响图片质量的状况下,巨细一般可优化在60%左右,关于自身很小的图片也能够进行紧缩(不过主张将紧缩前后的比照图让UI规划师把关)

这个是咱们批量紧缩User组件图片前后比照:

货拉拉 iOS 包大小优化探索与实践

关于单张图片,视觉上确实看不出紧缩的痕迹,参考下图:

紧缩前:72K

货拉拉 iOS 包大小优化探索与实践

紧缩后:16K

货拉拉 iOS 包大小优化探索与实践

咱们脚本流程:

货拉拉 iOS 包大小优化探索与实践

脚本代码:

留意:有些图片自身很小,紧缩后反而会增大,所以需求判别一下是否需求紧缩,脚本紧缩逻辑为:

check_files=`find $input_dir -name '*.png'`
for line in $check_files
do  
    pngquant --quality=20-30 $line
    pre_name=`echo $line | awk -F '.png' '{print $1}'`
    pre_name="${pre_name}-fs8.png"
    pic_size1=`wc -c $line | awk '{print $1}'`
    pic_size2=`wc -c $pre_name | awk '{print $1}'`
    if [[ $pic_size2 -lt $pic_size1 ]];then 
        mv $pre_name $line
    else 
        echo "原图${line},紧缩图$pre_name"
        echo $pic_size1
        echo $pic_size2
        echo "紧缩后图片巨细反而变大,抛弃此次紧缩"
        cp -fr $line $cannot_zip_dir
        rm $pre_name
    fi 
done
echo "将紧缩后的图片拷贝出来..."
check_files=`find $input_dir -name '*.png'`
for line in $check_files
do  
    cp $line "${zip_bundle}/"
done
rm -fr $origin_dir
echo "履行结束!!!"
exit 1
  1. 静态资源站点化

也能够将一些本地资源托管到自己的服务器或许CDN上,这样也能够优化安装包巨细,如H5资源,字体文件,较大的图片,音视频,App主题资源,需求留意的是,最好在不影响App发动功率的根底上评价施行;

  1. 选用webp格局图片

选用webp的理由是WebP 紧缩率较高,肉眼看不出差异,支撑有损和无损两种紧缩办法,依据 Google 的测验,无损紧缩后的 WebP 比 PNG 文件少了 26%的体积,有损紧缩后的 WebP 图片相比于等效质量目标的 JPEG 图片削减了 25%~34% 的体积,WebP 支撑 Alpha 通明和 24-bit 色彩数,不会像 PNG8 那样因为色彩不够而呈现毛边。

WebP 与JPG,PNG 相比照,编解码在CPU的耗费上以及功率上会差一些,假如是服务器图片,编码进程是在服务器后台进行,那么对影响较大的是解码进程,图片加载速度慢一些,这需求依据项目的实际状况在功能和体积上进行评价取舍。

留意:iOS自身暂不支撑WebP格局加载,可引进SDWebImage/WebP

转Webp东西:

  1. iSpart腾讯出品,GUI东西;
  2. webp指令行东西: 运用Homebrew进行安装:
$brew install webp
  1. 图标的优化

这种优化办法属于编码进程中需求留意的点,单个的收益不会太大,实践起来会比较繁琐,可依据项目要求进行这类精细化处理。

一般办法有:

  1. 运用 tint color 精简单色图标

单色图标处理(将单色图标渲染办法为UIImageRenderingModeAlwaysTemplate,如回来按钮,tabbar icon图标,会忽略自身色彩信息选用父控件tintColor色彩渲染)

  1. 图标字体(IconFont)替换单色图标
  2. 类似图标整合

4. Mach-O优化

安装包中的Mach-O可履行文件包括咱们的中心事务代码,它的巨细是由代码量来决定的,所以一般状况下,是需求找出项目中无用办法和无用类进行删去,当然,业界也有对从其他视点对Mach-O的巨细进行优化的。

  1. 静态筛查计划

设置Xcode的Build SettingWrite Link Map File为Yes,再指定Path to Link Map File的指向途径可得到编译后的LinkMap文件,这个文件包括Object File,Section,Symbols,包括了一切的类和办法,然后经过otool指令导出项目Mach-O中的__objc_selrefs、 __objc_class_list & __objc_class_refs 做差集找到未运用的Objc类及办法。

Mach-O中片段:

货拉拉 iOS 包大小优化探索与实践

linkMap文件片段:

货拉拉 iOS 包大小优化探索与实践

假如代码选用 C 、C++ 等静态言语编写代码时,编译期现已承认了根本的代码逻辑,所以编译器会协助咱们将没有运用到的代码符号为 Dead code 终究不会打包到安装包中。但Objc 是典型的动态言语,很多逻辑都是在运转时决议的,经过静态扫描的办法会存在较大差错,还需求二次承认,抖音关于这静态成果初筛的得到未运用类的准确性只有 24% (总样本 264 个,射中 64 个)。

2.动态筛查计划

  1. 依据插桩的行等级代码覆盖率:

依据 GCOV 或许 LLVM Profile 二进制的插桩计划能够完结在运转时搜集插桩数据来指导无用代码的删去。但插桩计划局限性也清楚明了,插桩会劣化二进制自身的巨细和功能,同时原生的插桩计划是无法过审上线。数据搜集只能局限于线下。

  1. 依据 Runtime 的轻量级运转时「类覆盖率」计划:

Objc 的类首次调用类初始化时,+initialize 被履行,体系会主动符号已被调用,在 metaClass 中 data 的 flags 字段第 29 位就存着这个这个状况。能够运用 flags & RW_INITIALIZED 获取。iOS14 之后这个值的获取办法有变化

#define RW_INITIALIZED (1<<29)
bool isInitialized() {
   return getMeta()->data()->flags & RW_INITIALIZED;
}

上报的数据能够让咱们了解咱们线上实在的 Class 运用状况,对得到的数据不只能够用来删减未运用的代码。还能够分辨运用率低的场景,假如是低频且有必要的场景能够考虑运用跨端技术这种对原生包巨细影响比较小的计划完结。而假如这些场景是某个浸透率很低的需求能够考虑直接下线为其他需求做置换。

5. Framework优化

安装包中Framework目录存放着咱们项目依赖的动态库,一般状况下苹果给咱们的主张是不超越六个,因为咱们的项目是组件化的,有些三方库,二方库经过Cocoapods引进时,是以动态库的办法引进的,动态库尽管自身产物比静态库小,但终究咱们的安装包中,动态库以几近拷贝的办法进入到咱们的包中,而静态库会经过静态链接进入到咱们的可履行文件Mach-O中。

App依赖Dyld构建包流程:

货拉拉 iOS 包大小优化探索与实践

1.探究静态库/动态库对包的影响

条件:平等状况下,运用:AFNetworking,SDWebImage,SensorsAnalyticsSDK别离作为静态库和动态库办法引进工程:

货拉拉 iOS 包大小优化探索与实践

IPA包巨细 补白
AFNetworkingWebImageSensorsAnalyticsSDK 作为动态库引进 3.6M
作为静态库引进 1M

经过试验,咱们发现动态库办法引进后对安装包全体的影响仍是比较大的,假如项目中存在较多的动态库,能够考虑转静态库进行优化。

6. 一些编码习惯的主张

1.封装&重构

收拾项目中的重复办法和逻辑,下沉到能够经过的模块中,还能够考虑对项目中的老旧耦合高的模块进行重构,必定程度上能削减代码量。

2.字符串常量办理,命名办理

项目中的局部字符串常量转成大局常量字符串,统一办理,字符串的命名设置必定标准,最好不要太长,文本比较长的字符串能够转成文本进行读取或许服务器变量下发。

3.Class Method vs C 函数

通常咱们关于一些根底和通用的函数会选用东西类的办法对外露出。运用类办法完结功用。但当咱们选用 Class Method, 这种办法在编译的时分需求生成 Class 的类结构。调用的办法会经过 objc_methodSend。假如选用 C 函数的办法能够减小这部分的开销。假如只是自己组件内部运用的私有的功用性函数仍是主张运用 C 函数的办法完结。

4.Property vs IVAR

Objc 关于 Class 的 property,会主动的生成 set、get 办法,比方这个 property 是 Class 的私有特点的时分,咱们能够直接运用 ivar 来替代 property。减小这部分的包巨细开销。这儿需求留意,当咱们运用 property 的 getter 完结 LazyLoad 或许 setter 存在一些其他副作用的时分仍是需求保存 property 的。

5.尽量防止代码片段复制粘贴

项目中或许有些办法或许函数能够被复用,但往往因为一些原因,如办法不能直接访问或参数不一致等原因终究被拷贝出去另起新办法,特别是组件化项目,组件之间的通信是有必定约束的,简单发生这类问题,主张将这些办法尽或许抽象出来以支撑多种状况,并抽离或下沉到公共模块中。

四. 防劣化计划规划

  1. 图片巨细把关

    1. @1x图不用集成,只需求2x,3x;
    2. 界说图片名标准,以英文命名,格局为: 图片分类_模块名_功用名,如:ic_orderdetail_scan
    3. 中小型图片主张用png, 可脚本先行紧缩或从头切图,再引进到项目中,完结开发后,如有做紧缩先让美工进行视觉检验;
    4. 一切图片尽量放xcassets统一办理;
  2. 资源阈值预警

货拉拉 iOS 包大小优化探索与实践

  1. 在构建发布包前,扫描增量资源文件,超越设定的阈值,发动报警机制,评价该资源引进的必要性或引进办法的合理性。
  2. 将扫描各组件未运用的资源的脚本植入打包流水线,打包进程中会履行扫描未运用资源,一旦扫描到就将资源清单发送给模块负责人。
  1. 三方库办理

针对指定的三方SDK图片资源,经过主动化构建发布包时,考虑在打包的打包流水线嵌入脚本进行收拾,紧缩,以防外部资源的劣化。

  1. 模块预警机制

模块巨细增量超越设定的阈值时,发动报警机制,对该模块添加的巨细进行评价合理性,是否有优化空间,启发咱们反思。

  1. 树立杰出的编码标准

制定杰出的编码标准,在团队中推行,实行开发人员的结对Review代码(按照制定好的编码标准),每个需求兼并到Release发布分支前,先Review审阅经往后再进行兼并。

五. 结论

本次首要是从编译器优化,资源文件收拾,图片紧缩,类/办法扫描,Framework治理、编码习惯主张,防劣化规划几个方面介绍了货拉拉iOS用户端在App包巨细方面优化的实践,有些思路是大多数App减肥优化通用的,App包优化是一个按部就班的进程,主张先易后难,比方先从优化资源文件方面入手,而且大多数状况下,资源文件优化的收益是最大的,最好每次优化后进行回归测验确保线上稳定,终究期望本文能给咱们在自家App包巨细优化时供给一些学习和思路。

参考:

Alibaba.com包巨细优化
探究 iOS 编码对包巨细的影响
抖音品质建造 – iOS 安装包巨细优化实践篇