乐趣区

关于react-native:React-Native-优化实践之拆包与预热

本文作者:段家顺

背景

随着 React Native 技术在业务中宽泛的利用,一些比拟重要的性能也开始采纳 React Native 的技术计划来实现,这就给 React Native 页面的关上速度提出了更高的要求,因为关上速度是影响用户跳出率的重要起因之一。

拆包

对于 React Native 关上速度优化,业界比拟通用的计划也就是预热 + 拆分根底包,缩小容器初始化工夫和根底库加载工夫。
对 React Native 进行拆包能够依赖于官网提供的工具进行,然而官网提供的能力是 JS 外部的一个拆分加载,如果咱们须要做容器预热,则无奈应用官网的加载计划,而须要咱们从客户端本来的逻辑中进行革新为多步加载。
咱们须要对 React Native 的逻辑进行革新,就须要对 React Native 初始化逻辑有所理解。

上图是一个大抵的过程,这里咱们对比拟要害的几个步骤进行简略的阐明。

  1. RCTBridge 在实例化之后,会首先筹备好 JS 运行线程和原生模块。
  2. 而后会创立一个 JSExcutor,这个执行器决定了 JS 执行环境是客户端还是近程调试(安卓能够是本人定制的执行器,比方 V8)。
  3. 加载源码(bundle),这个依据起源不同可能是从本地加载,也可能通过 url 从远端加载。
  4. 因为初始化 JS 执行器和代码是并行触发的,这里须要一个栅栏同步两者后果,之后开始将代码放入执行器执行(JS 代码运行)。
  5. 在此之后,客户端会监听垂直同步信号(该信号的作用是在页面产生变更的时候,须要从新刷新页面)。
  6. 此时 RootView 收到 JS 加载实现的告诉,开始触发 RunApp 逻辑,该逻辑就是启动前端的 app 注册表中对应的利用。

整个流程比拟长,然而分工还是相当明确的,此次拆包革新的中央也十分明确。

上图中绿色框内就是咱们此次革新的点,这里从实现简略与以后需要的角度登程,将加载代码设计为串行加载,如果须要进一步优化,加载过程也能够进行并发设计。
这里咱们对加载能力进行一次形象,加载一段代码定义为一个SourceLoader,那么一个拆包 bridge 就相当于有一个加载器列表,对应于 bridge 上的属性就非常简单。

@property (nonatomic, strong) NSArray<id<RCTBridgeSourceLoaderProtocol>> *preloadSourceLoaders;  // 预加载的加载器
- (void)preloadSourceWithCompletion:(void(^)(NSError *error))completion; // 触发预加载加载器
@property (nonatomic, strong) NSArray<id<RCTBridgeSourceLoaderProtocol>> *sourceLoaders;  // 非预加载加载器
- (void)loadSourceWithCompletion:(void(^)(NSError *error))completion;  // 触发非预加载器
- (void)loadAllSourcesWithCompletion:(void(^)(NSError *error))completion;  // 先加载预加载代码,再加载非预加载代码

这里有一个须要留神的点是,咱们须要启动一个垂直同步信号监听,为了性能思考,须要在预热容器加载到真正视图的时候能力开启,所以这里对加载器减少一个标记,只有加载到该加载器之后能力开启监听。
通过这样的革新,咱们的 React Native 就曾经反对了多包散布加载了。咱们就能够把一些根底性能的 JS 代码打包进利用外部,也缩小一些包大小。

容器预热

只有分包加载并不能对加载速度有太大的影响,而真正的优化点是容器的预热。预热能够将很多筹备工作先做了,在业务加载的时候只会触发加载业务代码与渲染页面。
受限于手机性能的局限,以及一些苹果官网的策略,咱们不太可能无限度的去应用该能力,所以这里按 3 个方面来看预热。
预热触发机会
目前预热触发的机会次要有上面 3 个点

  • 冷启动
  • 热启动
  • 容器复用之后

在这些机会触发之后,再提早肯定工夫(5 秒),进行创立预热实例。提早一会的起因是这些机会大概率都是在做一些 CPU 密集型工作,如果此时再退出创立预热容器这种非必须的工作,反而可能影响主业务的一些性能。
预热容器销毁
目前销毁的机会次要有上面 2 个

  • 内存正告
  • 进入后盾

进入后盾销毁的目标次要是为了升高后盾运行的内存,尽管这点内存占比不大,然而目前苹果对后盾运行的策略还是比拟严格的,所以咱们尽量减少存在的影响。
预热的场景化
因为 React Native 这种能力在咱们的业务中并不负责次要场景,可能大部分用户都不会应用到 React Native,而咱们对全量用户进行无差别的开启预热性能,也不是一种最优的形式。目前咱们还没有能力对用户场景进行机器学习这样的智能化剖析,那么这次就对一些场景做一下简略的归类:

  • 3 天内没有应用过 React Native 能力,则认为该用户后续也不会应用该能力
  • 3 天内没有因为内存正告而销毁的记录
  • 以后利用启动周期内:

    • 预加载失败 3 次,则该周期内不再启用预加载

容器预热的关键点是在不影响用户其余体验的时候,尽可能的进步预热的命中率,目前做的一些策略都比较简单,后续如果要优化,就须要深刻业务场景中。

成果

当开启拆包和预热能力后,商城页面包大小从整包 1.1M 缩小为 856K,页面关上时长在 iOS 里由 450ms 缩小到 200ms 左右,在安卓里由 4500ms 缩小到 2500ms,双端的优化成果都非常明显,阐明咱们的优化计划是十分无效的。

总结

此次 React Native 的优化分为拆包和预热两局部,各自能力独立,并别离进行 AB 管制,最大可能保障稳定性。后续将会深刻业务场景去做一些优化策略。

本文公布自 网易云音乐大前端团队,文章未经受权禁止任何模式的转载。咱们长年招收前端、iOS、Android,如果你筹备换工作,又恰好喜爱云音乐,那就退出咱们 grp.music-fe(at)corp.netease.com!

退出移动版