【腾讯Bugly干货分享】React Native项目实战总结

【腾讯Bugly干货分享】React Native项目实战总结

本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7

“8小时内拼工作,8小时外拼成长”这是大家共同的理想。除了每天忙于工作外,我们都希望能更多地区吸收领域内的新知识与新技能,从而走向人生巅峰。

Dev Club 是一个交流移动开发技术,结交朋友,扩展人脉的社群,成员都是经过审核的移动开发工程师。每周都会举行嘉宾分享,话题讨论等活动。

上一期我们邀请了腾讯SNG工程师“王少鸣”分享了《React Native项目实战总结》

2016-07-14,下周四,我们将邀请腾讯WXG iOS开发工程师“姚海波”为大家分享《微信读书iOS性能优化》

如何加入 Dev Club?

移动端开发经验 >= 2 年,微信扫描下方群管理微信二维码,备注姓名-公司(或产品) 申请加入。

【腾讯Bugly干货分享】React Native项目实战总结

———–下面是上一期分享内容整理———–

《React Native项目实战总结》

内容简介:

你是否想体验Web一样的发布节奏来发布终端的特性?

你是否想低成本让先前的H5特性拥有Native一样的流畅体验?

快来一起拥抱ReactNative吧!

分享人介绍:

王少鸣,社交平台部工程师。对前端系统的设计和开发有丰富的经验,先后从事PC Qzone前端开发,小Q机器人智能终端开发及微信群,手机Qzone终端开发等工作。

1

Hello,大家晚上好,我是来自QQ空间的王少鸣,大家可以叫我mango,目前主要负责 Qzone 玩吧业务,专注Hybrid开发,[QQJsSDK] 研发负责人,专注ReactNative在Qzone与手Q的应用和推广。照片里的这个人就是我,上周在GMTC分享拍的,请大家多多指教。

接下来进入正题,请大家先认识下这几个简写:

fb = Facebook
rn = ReactNative
jsc = Javascript Core
cxt = Context

ReactNative 让开发者使用 JavaScript 和 React 编写应用,利用相同的核心代码就可以创建 基于Web,iOS 和 Android 平台的原生应用。Facebook 在2015.9.15发布了 ReactNative for Android,把JavaScript 开发技术扩展到了Android平台,至此已覆盖当流主流平台。

2

目前ReactNative的版本节奏大概是两周一个版本,空间从11的版本便开始尝试接入,第一个上线的版本是15的版本,后面我们升级到20的版本,由于一些历史包袱的原因,导致我们升级并不能随时跟随fb的升级节奏。手Q方面目前使用的是17的版本。

3

我们从fb rn的官网中的showcase页面可以看到,目前已经有大量的app接使用了rn的技术,当前,还能看到我们公司的不少app,如QQ,Qzone,QQ音乐,全民k歌等,这个大家如果有兴趣想要把自己的app放到官网上,只需要要向fb提交一个pr即可。

4

目前在空间有三个业务使了用rn进行开发,有话题圈,情侣空间,结合版留言版等。在手Q方面,有消息流和资料卡等,当然,还有全民k歌的一些活动页。

接下来我们来对比下rn与原生开发或hybrid开发有些哪优劣势。

优势:

  • 原生控件的体验,Web的版本节奏,Web的开发效率,跨平台等

劣势:

  • 版本支持度 Android 4.1 (API 16) & iOS 7.0

  • 项目尚不成熟,容易Crash,部分机器存在兼容性问题

  • 性能,在高低端机呈现两极

  • Android仅基于Gradle,目前业界较多大平台项目均基于 Ant,如Qzone,手Q等

特别是最后一点,这个也是我们前面说的,版本升级不能跟随fb rn版本的原因,我们的每次升级都需要将rn源码进行改造和合并,接口适配等,对开发有一定的额外的工作量。

接下来,我们来看下,使用rn开发的版本整体流程。

5

首先,我们的app集成了rn的sdk,另外,jsbundle也就是我们使用rn开发的上层业务逻辑代码。我们在发布app时,我们会内置一份。当上层业务逻辑变化时,我们会重新向我们的cdn发布一份新的jsbundle。在app启动时,我们检查当时外网有没有jsbundle需要更新,如果有,我们们更新并存放本地。在点击应用入口时,我们会优先使用新下载的这份文件,否则使用内置的,最后通过JSC进行渲染,得到我们最终的页面。

ok,了解了版本的整体流程,再简单来看看rn原理。

6

前面我们讲到了jsc,那jsc就是桥接web<>native的一个组件,在一定意义上等同于我们的浏览器内核。那讲完jsc,那原理就比较容易理解了,就是通过jsc去解析我们的jsbundle,并将信息传递给native,最后由native不断去处理来自js层的调用,最终得到我们的native页面。

网上分析rn在iOS的文章也比较多了,我这边也不多讲,主要讲下在android方面的。

7

主要分为三层:

  1. java层:主要有ReactCore,主要处理与js的交互,还有处理图片的fresco,网络库okhttp,还有一些support和utils等。

  2. C++层:主要有我们的jsc,bridge,,jsloader等

  3. JS层:这层相对大家就比较熟悉了,主要是包含组件的逻辑处理和一些布局,当然,这些布局信息最终也是转成我们终端的布局模型。

接下来,我们来看一下js跟native的通信机制。

这块内容其实是rn里很重要的内容,这块主要是流程比较长,我们今天就简单讲一下,详细的有兴趣的同学,可以去公众号看我之前写文章,或者直接找我。

先来看看从java层到js层的调用。

8

我们的业务逻辑其实是在js里面,那就这里出现了我们的启动逻辑,这里其实就是java层到js层调用的一个例子,由java去调用js的某个启动函数。

那js层到java层的调用就更多了,比如像点击图片点看大图浮层,这里更多是业务性质的调用。

9

当然,还有另外一个可能大家比较关注的问题,就是前端写的标签,比如我们的<Text /> 这样一个组件,是怎么转换到终端的一个view?这里其实原理也很简单,js层会将控件标签转换成js对终端UI模块的一次调用,如比像这种UIManager.creaeView或者UIManager.removeView我们无论是java到js还是js到java,中间都必须经过我们的jsc进行桥接。

上一张稍微复杂点的调用链

10

这个讲起来时间稍微有点长,其实就是说明标签到控件的一个完整调用链,有兴趣的同学我们下来再讨论。

好了,前面原理讲得比较多,因为可能有先同学先前没接触过rn,我这里就先讲些基础知识。接下来我们讲些可能大家比较感兴趣的,就是我们踩坑和填坑之路。

那在接下rn之前,我们会遇到了下面几个问题:

  1. 包大小:Android HelloWorld工程 约7m

  2. 稳定性:业界尚未有真实外网数据,内部仅能通过大量机器进行稳定性测试,但未能覆盖所有机型

  3. 安全性:Jsbundle可能发生被拦截等情况,容易导致Native Crash

  4. 兼容性:Android 4.1 (API 16) & iOS 7.0 Jsbundle与Native版本兼容 支持版本对机型兼容

  5. 性能:业界尚未有真实外网数据,仅靠实验室有限数据支撑

基于上面这几个问题,我们决定第一个版本,使用rn来改造之前的情侣空间业务(H5),我们使用独立插件的技术来实现。

独立插件通过异步下载,并且,我们使用独立进程来承载它防止拖垮主进程,最后,再加个云开关,假如外网有问题可以随时将rn切到h5。

这里第一个项目的细节就不细讲了,在这个项目,主要是想通过这个第一涉水项目,我们发现了哪些问题,以及我们是怎么解决的。主要是首屏方面,我们通过实验log数据,得知wifi下,首屏将近6s才能完全渲染出来。其次,fps主观上没明显卡顿,中低端机对比老版本下降明显,这个两个问题。

11

接下来,我们决定进行第二个业务话题圈使用rn进行改造。背景是话题圈先前是h5的,里面的视频组件无法支持自己播放及续播相关逻辑,那组件开发相开发时间关系这里就不细讲,有兴趣大家可以下来讨论。

12

那我们将先前情侣空间的log进行分块,主要是 插件及进程启动 2.1s+RN上下文启动+1.1s 首屏数据+2s Render 0.9s。接下来我们分块解决这些问题。

【腾讯Bugly干货分享】React Native项目实战总结

插件及进程启动:消灭这份耗时其实比较容易,rn和Qzone集成并绑在主进程即可。但是集成我们遇到一个问题就是Qzone是基本ant的构建,rn是基于gradle的构建,两者无法直接融合,那只能是将rn改造ant的构建。(qzone改造gradle代价比较大,周期长)关于更改构建这里,大家可以去看我km的一篇文章即可,时间有限,便不细讲了。

那我们话题圈最终改造的计划是:

ant改造rn -> 集成到Qzone -> 业务开发 -> 性能优化

时间问题,我们着重看性能优化方面的知识,可能有些我也讲得不深,也有些针对性,希望能给大家带一些新启发更关键。

【腾讯Bugly干货分享】React Native项目实战总结

集成到Qzone主要是方法数的问题,那业务开发,我简单讲一个点,就是在开发前,终端同学需要与前端同学定制好你们业务的所有接口。这里我有个建议,形参建议只保留两个,一个是你们业务数据的json,另外一个就是cb。因为rn在接口调用方法,如果参数个数对不上,会直接导致应用crash。

【腾讯Bugly干货分享】React Native项目实战总结

那我们接下来看性能优化方面的东西,我们这里已经将Qzone与rn进行集成了,那关于插件启动和进程启动的耗时已经可以消除,那接下来我们看下,怎么去消除首屏和上下文的耗时。

那我们先来看一下,一个传统的启动流程:

点击入口 -> native cxt -> web cxt -> 前端发起数据请求 -> 回包 -> 渲染

很明显,这里的流程是串行的,那我们是不是把一些东西并行起来,或者提前先做呢?和其他启动优化类似,还是内存换时间,我们这里加了预加载的逻辑。

预加载啥呢?我们这里预加载的是native cxt。假如你们的业务在二级页的话,我觉得预加载是没啥问题的,当然在主页面或者整个app都是用rn的话,可能就得换种思路了。

另外数据的话我们是这样做的。首先,我们给前端提供一个数据模块,这个模块提供可以读写本地数据的接口。我们点击入口的时候,终端会先去拉后台数据并存到sdcard,那当我们点击入口,前端再使用的我们提供的数据模块,读取缓存的数据进行渲染。当时,我们前端还是照样会发请求给后台拉最新的数据,随后覆盖到sdcard,假如数据有更新话,前台页面再重新渲染。最终我们的首屏定格在1.5s左右。(由于话题圈页面相对比较重,我们之前使用的是wns-html技术,这个数据其实已经超越了之前该页面的首屏速度)

【腾讯Bugly干货分享】React Native项目实战总结

那首屏讲完了,我们来看下FPS,对比我们之前的情侣空间,我们这次FPS同样有很多的提升,其实很多的优化思路我们是从前端优化思想中借鉴过来,像FPS就是,我们做了以下的优化:

UI方面:

  1. 减少View层级嵌套

  2. 合理设置背景色透明

JS方面:

  1. JS层使Listview控件渲染数据,废弃使用ScrollView控件

  2. 避免滑动做过多事情,减少JS线程掉帧

最终FPS基本定格在53-54左右。

【腾讯Bugly干货分享】React Native项目实战总结

【腾讯Bugly干货分享】React Native项目实战总结

我们最后再来看一下包精简的方案。原始的rn接近7m左右,那里面是不是有些优化空间呢?很多人在说,我们平台也有自己的网络库,真得还得使用rn里面的okhttp么?图片库也是,不能复用么?其实是可以,我们一起来看下包精简。那包精简主要分为下面4部分:

SO:

  1. 放弃对x86的支持

  2. 借用TBS能力,移除JSC

Java:

  1. 去除暂时不需要Module&UIManager

  2. Release 去除Dev Support

Jar:

  1. 对接平台网络库(WNS,MSF),移除OKHTTP

  2. 对接平台图片库(ImageManager),移除Fresco

  3. 平台 Support 阉割库 复用补齐

Res:

  1. 移除无用的Res文件,language val

  2. 平台 Support Res复用补齐

【腾讯Bugly干货分享】React Native项目实战总结


接下来,我们来看下crash方面的一些小经验。我们从三方面来分析crash。

  1. 先来看看so层的crash,这层的crash会比较被动,因为基本没办法去解决,一般都只能等官方来更新解决,先前我们碰到一个处理cookie的crash,其实我们并没有调用那个api,但系统自己启动调用了,我们当时的解决方案是将java的调用入口注释了。当然,还有一些so兼容的crash等等。

  2. java层的crash相对还好,源码在手,天下任走,这块我们可以随意修复,但建议是自己一定要把修改备注好,否则后面升级等都是灾难。

  3. 最后来看看js层的crash,前面几天我在gmtc分享的时候,就有个兄弟专门过来我问了我这个问题,他们遇到了js层一些属性转换的问题,并且直接表现就是实然crash。那这个问题,其实也困拢了我很久,我这边也没太好的解决方案,我们和前端同学定位过,属性类型肯定是没问题的,最后我们时间问题,解决方案是改动源码。源码在处理属性等问题上,稍微一言不和就直接throws exception,那我们这里临时的解决方案也只能是将throws改动log的标记,临时解决然后静等升级。

【腾讯Bugly干货分享】React Native项目实战总结

【腾讯Bugly干货分享】React Native项目实战总结

这里再稍微讲一下,我们在手Q方面的一些实践,当然这块参与的同学比较多了,这些也不单单由我一个人完成的。先来看一下我们这边又做了哪些优化。

主要有以下两方面:

  1. 分包。前面我们讲预加载的知识。我们当时预加载的仅是native cxt,那我们可不可以把前端cxt也加载了呢?其实肯定是可以 ,我们试过直接预加载到整一个view的级别,但是,这样会增加近40m的内存,当然是秒开,但是还是要保证内存和首屏的权衡。后来,我们进一步思考,假如后续业务众多,每次业务切换是否每次都去重新加载那个1m多的jsbundle呢?后来,我们有了另外一个方案,就是将jsbundle进行拆分为base和busi两个zip。base我们进行预加载,并且,我们在业务切换的时候,我们会进行复用,能更有效地提高首屏的速度。

  2. 独立进程操作so。这个主要是因为手Q对内存要求比较严格,在界面退出的时候所有连带内存必须清理干净。那rn在这方面其实做的并没有那么好,有部分so层的内存一直占用着。那我们解决方案只能是将JNI拆分为独立进程并且在界面退出时,直接退出dalvik,回收所有内存。当然,这里就有些老技巧了,无非是进程预加载和延迟销毁。

【腾讯Bugly干货分享】React Native项目实战总结

接下来,我们看下整体在手Q这边次优化后,我们整体的数据对比

【腾讯Bugly干货分享】React Native项目实战总结


最后,我们分享下几个工具:

ReactNative Tools

  • adb logcat *:S ReactNative:V ReactNativeJS:V

  • Developer menu.

System Tools

  • 调试GPU过度绘制

  • GPU呈现模式

Android Tools

  • TraceView

  • Memory Monitor

  • TraceView

  • SysTrace

【腾讯Bugly干货分享】React Native项目实战总结

好了,今天分享就到这了,感谢大家耐心听我叨叨了这么多,谢谢大家,如果大家有疑问的话,可以按序发在群里,能力范围内的我按顺序回复大家,感谢!

问答环节

Q1:rn中用到js实现的逻辑容易出现性能问题吗?

A1:性能瓶颈还是在终端上,前端目前暂没发现严重的性能问题。

Q2:目前的空间和QQ都是部分使用RN,后面会继续扩大使用范围吗?

A2:肯定会的。rn目前是快速成长期,我们对rn有长期的归划。同样,希望更多兄弟团队一起来推动rn的成长,一起来贡献一份力

Q3:之前听到外界有团队抱怨 RN 相对原生来说组件太少,反而加大了开发量,什么都要自己来,现在是否有改善了呢?

A3:目前来看,其实组件是满足大部分开发者的,除非像某特些定制化的组件,比如像emojtext这种,我们才需要自己去自定义,当然,现在git上面也很多rn的组件了,应该能满足你

Q4:刚才分享的一些crash的例子好像都会导致rn直接崩掉,那你们用什么手段来定位究竟是那段js代码导致问题呢?

A4:这里还要讲明一点。主是掌握源码才有真正的主动权。很多问题,我们也都是去阅读源码发现的。其实源码并不复杂,里面很多知识沉淀,我个人是非常建议去读源码的。

Q5:我是做安卓的,不知道要不要尝试一下这个新技术? 现在团队做一些应用也不是很重,安卓和ios搞两套实在有些蛋疼

A5:android iOS两套这个问题,其实只是某些基础组件属于平台特有,但大部分逻辑还是有共性的。

Q6:目前rn发展还未稳定,预测一下未来是否会大规模应用并取代传统的native开发,真正实现一次编写,到处运行?

A6:动态更新其实这个问题很早前就有人提出,像插件啊,热更新其实目的也是一致的,rn只是另外一钟思路,weex也类似。完全取代native 开发个人觉得不太现实,因为像rn还是需要native的一些开发工作的。

Q7:自定义ui组件需要对rn适配吗?

A7:需要。但适配工作量并不高,仅对接相应接口,暴露一些属性即可

Q8:RN整套框架是基于原生构建的,UI接口升级的时候整套框架能够及时保持兼容吗?

A8:这里还要说明一下,jsbundle的版本跟native的版本其实是不兼容的。这里建议jsbundle的url都使用后台下发。另外,接口在升级后可能会有些改变,这里需要前终端一起配合

Q9:rn跨平台的话是不是还是需要维护两套js,只是有些组件可以跨平台共用呢?

A9:其实维护的js代码是一套。但可能在构建成特别平台的jsbundle前有小小的修改。大部分组件还是可以复用的,除了平台特有的,比如像actionbar这种

Q10:关于使用rn遇到的crash情况,你觉得rqd可以在哪些方面优化,帮助更好解决问题?

A10:目前业务使用rn的大平台还比较少,其实很多crash我们也在放量外网之后才发现的。这里我比较建议是在使用rn前,先大致读下rn的源码,并正式发布前多加一层保险开关。当前,目前就qzone使用的版本我也提交了一些pr,有些也收录了,后面相信 crash等会越来越少的

Q11:从Android的机型问题看,最怕的就是平台还不成熟,并且还开源。rn会不会重蹈覆辙?

A11:rn目前是开源的。目前开发者社区都是高活跃,应该不会存在kpi项目之类的问题,并且动态更新肯定是趋势,我觉得可能会有其他方案,但暂时来看,rn还是相当优秀的解决方案的

更多精彩内容欢迎关注bugly的微信公众账号:

【腾讯Bugly干货分享】React Native项目实战总结

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/108949.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • FreeWebHostingArea_Freefilesync

    FreeWebHostingArea_Freefilesync http://bbs.et8.net/bbs/showthread.php?t=896519hostingsiteshttp://www.orbitfiles.com/http://filexoom.com/http://www.sendthisfile.com/http://www.albumtown.com/http://app02.bonpoo.com/f

  • IDEA安装阿里代码规范插件

    IDEA安装阿里代码规范插件要养成一个好的编码习惯从自己编码开始,对自己代码的合理化命名,编码不仅对自己有好处,而且别人也容易读懂你的代码。所以下载阿里的代码规范插件来约束自己凌乱的代码。阿里规范插件GitHub地址:https://github.com/alibaba/p3cIDEA安装该插件步骤:1.打开IDEA,File-&gt;Setteings-&gt;Plugins-&gt;BrowseRepositorie…

  • 常见动态路由协议_动态路由协议执行哪两项任务

    常见动态路由协议_动态路由协议执行哪两项任务路由器要转发数据必须先配置路由数据,通常根据网络规模的大小可设置静态路由或设置动态路由。静态路由配置方便,对系统要求低,适用于拓扑结构简单并且稳定的小型网络。缺点是不能自动适应网络拓扑的变化,需要人工干预。动态路由协议有自己的路由算法,能够自动适应网络拓扑的变化,适用于具有一定数量三层设备的网络。缺点是配置对用户要求比较高,对系统的要求高于静态路由,并将占用一定的网络资源。      常见的动态路…

    2022年10月24日
  • origin如何在柱状图上面显示数据_origin柱状图横坐标自定义

    origin如何在柱状图上面显示数据_origin柱状图横坐标自定义经验:Origin做柱状图常遇问题/柱状图X坐标轴如何设置—小技巧对于每个搞科研的人来说,origin这个作图软件是必不可少的!但是,对于新手来说(我也算是半个新手*^__^*),它有时候显得有点高深,不知道该如何设置。就拿这次来说吧,同门要画一个性能随含量变化的柱状图(希望大体效果希望如上图,上图还没完全设置好),但是不知道该如何设置X坐标轴,因为含量的变化区间不是固定的,例如10%,20%,4…

  • MBus总线的基础学习

    MBus总线的基础学习MBus总线是一种主从式半双工传输总线,采用主叫/应答的方式通信,即只有处于中心地位的主站(Master)发出询问后,从站(Slave)才能向主站传输数据。MBus的主要特点如下:1、两线制总线,不分正负极性,施工简单;2、采用独特的电平特征传输数字信号,抗干扰能力强,传输距离长;3、可以选着总线供电,降低维护成本;4、总线型拓扑结构,扩展方便,组网成本低;5、任一

    2022年10月16日
  • Mysql 练习题 及 答案

    Mysql 练习题 及 答案 –1.学生表Student(S,Sname,Sage,Ssex)–S学生编号,Sname学生姓名,Sage出生年月,Ssex学生性别–2.课程表 Course(C,Cname,T)–C–课程编号,Cname课程名称,T教师编号–3.教师表 Teacher(T,Tname)–T教师编号,Tname教师姓名–4.成绩表 SC(S,C,score)–S学生…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号