RN-Android发行包精简初探

RN-Android发行包精简初探

众所周知,随着迭代版本的增加,缩减 React-Native 的 Android 发行包的大小将成为开发人员需要面对的问题之一,究竟如何来做既可以避免引发未知的BUG,又可以有效缩小安装包大小?接下来,我将其分为两个角度分别叙述:

  1. 在应用开发的前期我们能做什么?
  2. 木已成舟,面对已经臃肿不堪的发行包如何补救?

在应用开发的前期我们能做什么

1. 缩减图片的使用 & 使用webp

避免在纯色以及渐变的UI部分使用图片,不仅可以缩小安装包体积,还将获得极快的渲染速度,也不用考虑适配问题。

考虑是否使用 webp 格式的资源图片取代 png 图片,当然这仅适用于有大量图片存在的移动端应用程序,同时在服务端开发的过程中也需要进行针对性的优化(例:用户上传后的图片亦需要服务端转码为 webp 格式,缩减请求的资源大小,将有效提升程序的整体响应速度)。但由于 iOS 系统对于 webp 的支持不佳,需要引入第三方包支持。这也造成 iOS 原有的@2x @3x按照设备加载对应图片的机制失效,将影响图片加载效率。

webp 格式图片分为多种,既有 有损压缩无损压缩,也有动态静态 两种模式,应当谨慎选择。

2. 避免使用帧动画

一个简单的帧动画也会包含数十张图片,无论如何压缩,终究会占用大量的空间。因此应当避免使用帧动画,以UI动画来完成,使用 lottie-react-native 将是一个不错的选择。

3. 前期规划

前期的规划极为重要,究竟要使用哪些第三方包?应当及早的做出技术选型,避免中途更换,造成代码冗余。即使因为不可抗力需要更换第三方组件,也应当即时清理原先选用的第三方包带来的冗余依赖及代码。

木已成舟,面对已经臃肿不堪的发行包如何补救

在这一步,我们也应当将其一分为二来看待,分别从 react-native 以及 Android 原生开发 两个角度进行分析。

首先,从我们正在开发的APP进行分析,如下图所示:

lib/:包含特定于处理器软件层的编译代码。该目录包含了每种平台的子目录,如armeabiarmeabi-v7aarm64-v8ax86x86_64,和mips 以及 mips64

assets/:包含应用可以使用 AssetManager 对象检索的应用资源。

res/:包含未编译及无法编译的资源,主要包含图片、音频资源文件。

classes.dex:包含以 Dalvik/ART 虚拟机可理解的 DEX 文件格式编译类。

kotlin:-

okhttp3:网络请求的开源框架的相关文件。

AndroidManifest.xml:包含核心 Android 清单文件。该文件列出应用程序的名称,版本,访问权限和引用的库文件。其采用 Android 的二进制 XML 格式。

META-INF/:包含 CERT.SF 和 CERT.RSA 签名文件以及 MANIFEST.MF 清单文件。

如果您仔细观察,则会发现存在 DownLoad SizeRaw File Size 两种大小,其中的 Raw File Size 是指原始文件的真实大小,即app解压后占用的真实空间。而 DownLoad Size 则是指分析工具预估的从 google play 下载本应用所耗费的网络流量大小。

通过上述的分析图可知,lib/ 文件夹中的 so 文件占用了最大比重,接近70MB。其次是 assets 目录,占用了28M,第三则是资源文件res目录了(注:res文件夹偏小,是因为所有的图像文件均已经过tinyPNG压缩处理)。

lib/ 文件夹精简

作者注:由于网络中技术文章流传的 abi 的各版本描述均已过时,请以本文中对各版本 abi 的描述为准。

我们根据 google-Android 提供的最新文档:

mipsmips64 已明确被官方弃用。故此,开发者无需再集成使用。

而上图中未提到的 armeabi 于 ndk-r16版本中被弃用,r17版本中被彻底移除。因此不难得出结论:此版本的 ABI 均应该从我们的应用中移除。

而上图中提到的 x86 以及 x86_64 两种 ABI 一般适用于 老旧的平板电脑、老旧的客厅HTPC、以及部分安卓模拟器(注:截至2020年2月,大部分的安卓模拟器已从软件的方式适配armeabi-v7a),所以,非及其特殊的情况,亦无需集成上述的两种 ABI。

ABIs介绍建议备注armeabi为 ARMv5ARMv6 两代CPU架构提供支持,这些设备目前在消费市场占有率已不足1%无需集成-armeabi - v7a为 ARMv7 架构提供支持,本架构的CPU在消费市场设备留存率中排名第一需集成-arm64 - v8a目前最新的CPU架构支持包,google 官方应用市场已发出通知2019年8月后发布的APP必须集成本 ABI需集成本ABI将有效提高新手机上APP的运行效率x86适用于支持通常称为 x86i386IA-32 的指令集的 CPU无需集成-x86_64适用于支持通常称为 x86-64 的指令集的 CPU无需集成-mips官方移除支持无需集成-mips64官方移除支持无需集成-

因此,在通常情况下,我们仅需保留两种ABI:armeabi-v7aarm64-v8a 根据此方案,结合现有程序,将节省 38.1MB,减少33.3%的空间占用。

React-native 官方推荐的优化工具:Proguard

Proguard 是官方提供的一个混淆压缩工具,其既可以精简掉 React Native Java(和它的依赖库中)中没有被使用到的部分,也可以混淆代码,提供一定的加密能力。

注意:启用本功能(则无需启用下条提到的shrinkResources方法),可能会导致app出现新的错误,你可在 Proguard 功能所提供的 app/proguard-rules.pro 文件中填写相应的精简排除项,在第三方库的文档中能找到这些配置项。

要启用 Proguard,修改android/app/build.gradle文件:

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */

def enableProguardInReleaseBuilds = false

Android 原生开发常用优化工具:shrinkResources

/app/build.gradle 文件中可开启 shrinkResources 功能。当其值为 true 时,表示在编译时自动移除没有引用到的资源文件,主要包括:layout布局文件和drawable图片文件。其处理方式是保留文件,但是内容置空

注意:本功能的本意是删除冗余,降低编译后的apk包大小。但在某些情况下,这个参数可能导致资源加载失败的问题。如:项目中使用了反射机制来加载图片或布局,如果刚好这些资源文件没有被其他方式引用的话,那么这些资源就会被误判,而被置空。

虽然保留文件,内容置空的方式可避免APP因此崩溃退出,但会直接导致很多令人困惑的错误现象。

打开 /app/build.gradle 文件,需要前置开启 minifyEnabled trueshrinkResources 依赖其生效,具体如下:

buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }
        release {
            // Caution! In production, you need to generate your own keystore file.
            // see https://facebook.github.io/react-native/docs/signed-apk-android.
            //混淆
            minifyEnabled true
            // 移除无用的resource文件
            shrinkResources true
            ...
        }
    }

开启后如出现故障,需要添加精简排除对象,可进行如下操作:

  1. app/src/res/ 文件夹中新建 raw 文件夹,添加 keep.xml 文件:
  1. 内容包含 <resources> 标记的 XML 文件,示例如下:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
           tools:discard="@color/selector_tint_color"
           tools:keep="@layout/activity_test1,@layout/activity_test2"
           tools:shrinkMode="strict"/>
    <!--tools:discard:做严格检查-->
    <!--tools:keep:不做严格检查-->
    <!--shrinkMode="strict" :该模式只保留在代码或者资源文件中明确引用的资源-->
    <!--shrinkMode="safe" :该模式会保留所有明确引用的资源以及可能被 Resources.getIdentifier() 动态引用的资源-->

湘ICP备18004308号-1 湘ICP备18004308号-2