React Native JS Module 加载性能优化

简介: 关于React Native 性能 React Native 在手淘中已开始逐步推广, 在拍立淘首页的使用场景中,我们发现React Native并没有想 象中的那么快,实测效果在离线状态下性能甚至比不过H5 WindVane,React Native的UI会出现延迟渲 染存在视觉差,经过具体

关于React Native 性能

React Native 在手淘中已开始逐步推广, 在拍立淘首页的使用场景中,我们发现React Native并没有想

象中的那么快,实测效果在离线状态下性能甚至比不过H5 WindVane,React Native的UI会出现延迟渲

染存在视觉差,经过具体的代码性能测试,整个过程平均在300 ms (IPhone 5S机型下,整个JS文件

400K), 然后其核心系统调用代码加载解析整个JS (JSEvaluateScript)耗时在220 ms左右,在目前

手淘的使用场景中,每个业务独立发布的JS大小都在400K左右,其中大部分属于系统接口JS,业务JS

的逻辑代码只占很小一部分,每个业务都创建RCTBridge 独立加载整个400K JS文件,重复的加载过程

和过大的离线JS文件(系统JS冗余)对性能和存储空间造成极大的开销,因此,优化拆分整个JS,动

态加载业务JS,管理JS缓存,避免重复加载,成为了优化React Native性能的核心。

React Native 优化设计

在实践过程中,将系统部分JS抽离出来打入APP本地资源中,初始化过程中先加载本地系统资源JS模

块,为了避免系统JS资源的释放和缓存的重复使用,RCTBridge 采用共享单例的设计模式实现,所有业

务方共享使用全局RCTBridge,共享使用优先加载系统JS缓存,动态管理加载每个业务方Module

URL到缓存并重复使用,根据每个业务JS的使用情况,动态管理缓存队列,清理缓存中长期未使用的业

务JS Module。

React Native 优化实现细节

技术上采用类扩展去除对源码的任何影响,RCTBridge (bizModule)通过单例模式实现系统JS的预先加

载和共享,代码示例如下:

`+ (instancetype)sharedBridge {

static dispatch_once_t pred;
static RCTBridge *instance;
dispatch_once(&pred, ^{
    NSURL *bundleURL = [[NSBundle mainBundle] URLForResource:@"system_ios" 

withExtension:@"js"];

    instance = [[RCTBridge alloc] initWithBundleURL:bundleURL moduleProvider:nil launchOptions:nil];
    instance.viewBindings = [[NSMutableDictionary alloc] init];
});
return instance;

} `

同时增加对外接口加载业务JS Module,建立从Module URL到Module Name 的缓存MAP关系,未加载

此Module则加载此Module URL,加载过则直接回调rootView bundleFinishedLoading加载显示

rootView,采用此种回调是为了避免影响原有逻辑NSNotificationCenter的通知,通过

RCTJavaScriptLoader 加载JS,调用javaScriptExecutor executeApplicationScript, 修改

RCTSourceCode,去除 jsDisplayLink和javaScriptExecutor executeJSCall:@"BatchedBridge"

method:@"flushedQueue" 的重复调用,接口函数如下:

`- (void)loadModuleURL:(NSURL )bundleURL moduleName:(NSString )moduleName rootView:
(RCTRootView *)rootView`

同时扩展RCTRootView (bizModule) 增加入口函数(去除对原有代码结构的影响):

`- (instancetype)initWithModuleURL:(NSURL )moduleURL moduleName:(NSString )moduleName launchOptions:(NSDictionary *)launchOptions {

RCTBridge *bridge = [RCTBridge sharedBridge];
[bridge loadModuleURL:moduleURL moduleName:moduleName rootView:self];
return [self initWithBridge:bridge moduleName:moduleName];

}`

React Native 后续优化方向:

目前基于此优化之后,在拍立淘首页运营的React JS性能评测从之前的300ms,优化到目前50ms以

内(IPhone 5S机型下已感觉不到视觉差),预计下个版本上线后会加入准确的性能埋点统计,优化后

续考虑加入Module JS 缓存机制,长久未使用的Module JS 会自动清理,经常使用的Module JS 会常驻

内存中,避免业务Module JS的重复加载所带来的开销,Module JS的管理也会逐步增加对外查询接

口,更新接口,注册预先加载接口等功能 ,一些新的想法和优化思路大家可以一起交流探讨。

目录
相关文章
|
2月前
|
JavaScript 前端开发 算法
js开发:请解释什么是虚拟DOM(virtual DOM),以及它在React中的应用。
虚拟DOM是React等前端框架的关键技术,它以轻量级JavaScript对象树形式抽象表示实际DOM。当状态改变,React不直接操作DOM,而是先构建新虚拟DOM树。通过高效diff算法比较新旧树,找到最小变更集,仅更新必要部分,提高DOM操作效率,降低性能损耗。虚拟DOM的抽象特性还支持跨平台应用,如React Native。总之,虚拟DOM优化了状态变化时的DOM更新,提升性能和用户体验。
30 0
|
1月前
报错/ ./node_modules/axios/lib/platform/index.js Module parse failed: Unexpected token (5:2)怎么解决?
报错/ ./node_modules/axios/lib/platform/index.js Module parse failed: Unexpected token (5:2)怎么解决?
|
11天前
|
SQL 存储 前端开发
React&Nest.js全栈社区平台(五)——👋封装通用分页Service实现文章流与详情
React&Nest.js全栈社区平台(五)——👋封装通用分页Service实现文章流与详情
React&Nest.js全栈社区平台(五)——👋封装通用分页Service实现文章流与详情
|
11天前
|
存储 SQL 前端开发
React&Nest.js社区平台(四)——✏️文章发布与管理实战
React&Nest.js社区平台(四)——✏️文章发布与管理实战
|
11天前
|
存储 前端开发 API
React&Nest.js全栈社区平台(三)——🐘对象存储是什么?为什么要用它?
React&Nest.js全栈社区平台(三)——🐘对象存储是什么?为什么要用它?
|
11天前
|
存储 前端开发 中间件
切图仔做全栈:React&Nest.js社区平台(二)——👋手把手实现优雅的鉴权机制
切图仔做全栈:React&Nest.js社区平台(二)——👋手把手实现优雅的鉴权机制
|
11天前
|
前端开发 NoSQL 数据库
切图仔做全栈:React&Nest.js社区平台(一)——基础架构与邮箱注册、JWT登录实现
切图仔做全栈:React&Nest.js社区平台(一)——基础架构与邮箱注册、JWT登录实现
|
1月前
|
JavaScript 前端开发
EasyUi js 加载数据表格DataGrid
EasyUi js 加载数据表格DataGrid
|
1月前
|
JavaScript
理解DOM树的加载过程(js的问题)
理解DOM树的加载过程(js的问题)
10 0
|
2月前
Module build failed (from ./node_modules/eslint-loader/index.js)
Module build failed (from ./node_modules/eslint-loader/index.js)
108 0
Module build failed (from ./node_modules/eslint-loader/index.js)