ReactNative 启动优化实践

RN 启动简介

Dive into React Native performance
阐述了基于RN实现的页面各部分加载时间占比图

image

页面加载流程图(引用)

image
image

从业务视角可以归纳为四个部分

  1. Bundle包准备:客户端Bundle包下载、解析等过程
  2. 初始化引擎:引擎准备,RN执行环境
  3. 加载Bundle:引擎加载JS代码
  4. 渲染Bundle:执行JS中runApplication()方法,开始渲染

RN 启动优化实践

包生产

  • 分包
    • 分业务分包:页面维度单独成包,避免大文件包
    • 分层分包:页面和组件拆分,便于复用,同时也减少了整体体积
  • 拆包
    • 一种方案,将一个包整体的index.js,拆分成一个入口+多个子模块,从而实现页面模块维度懒加载功能,减少页面首次加载时间,webpack和react loadable都有提供了切割能力
    • 另一种方案,RAM bundles和内联引用
      • RAM bundles:Indexed RAM Bundle和File RAM Bundle两种实现,将每个模块拆分为独立文件
      • 内联引用(inline requires):内联引用(require 代替 import)可以延迟模块或文件的加载,直到实际需要该文件。
  • 包大小优化
    • 包大小分析工具
    • 引入tree-shaking将无用代码删除
    • 静态资源压缩,重点图片

包下载

  • Bundle包缓存策略优化,减少下载时间
    • 核心或者重要页面直接预装
    • 本地增量更新策略
  • Bundle包下载策略优化,根据页面深度区分下载时机,实现延缓下载,减少首次并发下载任务量

包加载

  • 业务容器层加载JS的引擎,使用引擎池技术,默认空引擎+引擎复用,减少引擎池初始化时间
  • 底层引擎可以根据业务进行替换,使用V8或者Hermes React Native Memory profiling (JSC vs V8 vs Hermes

包渲染

  • 数据层
    • 本地化数据优化,数据缓存、前一个页面数据带入后一个数据
    • 数据请求异步加载,且尽可能提前请求,譬如执行js加载到内存
  • 模块层
    • 模块=页面一个个模块,对于复杂或者长的页面,简单理解可以是预先加载可见模块,然后在加载非可见模块。
  • 组件层
    • 减少重复渲染,例如pureComponent、Immutablejs、 列表 & Key、慎用setState
    • 其它React布局和渲染的一些常规优化

列表

官方推出的FlatList及SectionList的一些问题

  • 元素懒加载:元素只有出现在屏幕中,才会被初始化出来。
  • 无复用池机制:且初始化后不销毁:在元素离开可视范围后,会被同尺寸的空白元素替换,但是不会被销毁。另外FlatList中item的viewTree并没有真实复用,随着滚动渲染出来的viewTree越来越多,内存开销过大容易出现OOM
  • 异步渲染:在空白元素滚动到可视区域后,会进行UI渲染,先创建了一个等高空白容器,然后整个cell的viewTree异步渲染完成后再添加到空白容器内。所以快速滑动的时候,由于异步任务堆积,导致无法快速展现出现白屏。

官方对列表的一些配置推荐和实现建议 Optimizing Flatlist Configuration

  • Props
    • maxToRenderPerBatch,最大预加载数,即屏幕外渲染的Item数目
    • updateCellsBatchingPeriod,批量更新Cell周期,即批处理更新时间频率
    • initialNumToRender,初始化最大渲染数
  • List Items
    • 尽可能使用基础组件、轻量化组件,Item尽可能低层级、少逻辑
    • 使用shouldComponentUpdate来优化diff判断,从而减少重复渲染
    • 图片控件缓存优化,例如推荐react-native-fast-image优秀的图片控件
    • 通过getItemLayout告知高度,减少layout时间
    • 使用 列表 & Key,加速更新Diff计算
    • 避免匿名函数,每一个函数是一个新的对象

列表实践过程中的思考

OOM(增加复用能力)

实现Cell复用:一种思路是Native列表 + RN Cell,借助Native列表实现Cell复用能力,需要做以下几个事情

  • Native列表渲染Cell,在没有RN Cell的时候需要占位,有Cell的时候需要展示
  • Native列表Cell复用情况下,需要复用正确RN Cell,Cell之间关联关系处理
  • Native渲染线程全部在主线程同步执行,但是RN渲染是经过JS -> Shadow -> Native 三条线程异步操作,所以需要主动进行通信机制管理
白屏(减少通信或者提高通信速度)

Native与RN通信频繁是带来白屏的主要原因,那么可以结合一些特定的业务场景进行一些优化

  • 新一代的RN重构框架Fabric会重点优化线程通信效率,敬请期待
  • RN侧自己感知View变更,作出更新操作,而不全依靠Native通知,从而减少通信。例如顶部、底部上下移动带来新的View渲染,点击回到顶部,直接服用首页View等RN侧处理操作
  • 快速滑动限速,一般来说快速滑动是一个非常规操作,我们可以将速度限制到合理范围,减少过多的异步任务并发出发

参考:
React Native之启动流程
Tree-Shaking性能优化实践 - 原理篇
ReactNative 性能

你可能感兴趣的:(ReactNative 启动优化实践)