做者:Chen Feldmanhtml
发布日期:2019.07.30前端
原文连接:medium.com/swlh/react-…react
翻译中有部分是意译。ios
最近几年,React Native已经成为最流行的移动端App开发框架之一。解决了不少开发者常常思考的问题:应该使用原生开发客户端app,仍是使用web开发Hybird app。git
使用RN开发须要web方面的知识和React经验,由于它基本是基于React框架的。须要比直接使用Cordova这样库更难一些,可是比写Swift和Kotlin 这两个原生客户端的代码要轻松不少。RN能够经过写纯js代码得到和原生相似的性能体验。github
在开始以前,咱们先介绍一下,相比于其余方案,React Native的定位是什么。web
从左到右,能够分红3个阵营:objective-c
原生Native。这意味着你想去使用原生语言开发App,好比ios的Swift或Android的Kotlin。确定会得到最好的性能,而且能够充分利用设备硬件和原生API。可是,这须要学习两种不一样的编程语言,维护两套代码,而且可能有双倍的bug,甚至须要有两个不一样的开发团队。编程
Hybrid。若是你是web开发者或者拥有一个已经熟悉JS、HTML、CSS和某些前端库的Web团队,你能够选择这种方案,并使用Cordova/Ionic 经过一些步骤使你的网页变成移动App。这样咱们只须要学习一个技术栈,可是,在性能,硬件和API的使用上会有限制。react-native
类原生(其实也算是一种Hybrid)。React Native就属于这类,理论上开发者只须要懂得Web开发知识就能够了。可是学习曲线会比Hybrid要高一些。开发者须要学习怎么使用React Native的库。在某些场景下,可能还须要使用XCode或Android Studio打开项目。可是写的代码能够适用于iOS和Android两个平台,开发上的限制也会比Hybrid要小一些。性能表现会更像原生开发,并且能够更容易地使用一些原生的API。
如今咱们理解了RN的定位,让咱们对比一下RN和Hybrid的渲染状况:
从上图能够看出,使用Cordova的App是放在webView里的。这更像是一个在App里的浏览器。用web的概念说,这更像一个web app里的iFrame。
左边展现了React Native是怎么组成的,在RN中的每一个组件,好比:Text、Button、Image等都有一个相对应的原生组件。因此和不少新接触RN开发者想的不同,RN并无编译成原生代码,它作了个JS组件和原生组件的映射。
当咱们这样在Render函数里写了个RN组件:
背后部分预先写好的原生组件会是这样的:
若是咱们用iOS来举例,这些是RN里面的原生组件代码:
总的来讲,RN团队已经为咱们建立和映射了全部的原生组件。咱们须要去作的只是去基于RN组件和库写JavaScript代码。其余的部分对通常开发者来讲都是不可见的,像黑魔法同样。
因此,看上去咱们只用写js代码就能够了。让咱们一步步来解释一下这个架构是怎样的。从Bridge开始是最合适的:
RN能够分红JS 和 Native两部分,这两部分都有本身的线程
线程通讯是经过Bridge通讯,传输的是JSON信息,其中包含了module id,method id和一些须要的数据。这两边并不能直接地相互感知,也不能共享相同的内存。
这有点像不一样服务器之间通讯,若是你有用不一样语言写的后台服务,你将怎么在他们之间通讯呢?
不少人认为队列是一个很好的解决方案。你发送JSON/XML队列消息,这个消息听从相应的协议,而且每一个服务都知道怎么去读取和解析成对应的数据和行为。这个队列就很像RN里面的Bridge。
这里有个例子展现通讯是怎样进行的,信息被发送到Bridge。从建立新的View和样式并在屏幕上显示,到在移动端设置子组件和进行一些操做:
若是想要在console里看到Bridge的消息,只须要把下面这个代码片断放到index. < platform > .js里就能够了
如今咱们知道了RN是怎么通讯的,而且开始揭晓其中的“黑魔法”。
这也是为何Android App须要更多的时间去加载,由于须要加载JSCore到项目里。不过在0.60.2以后,RN可使用Hermes,这对于RN来讲是更理想的JS引擎。
在这部分,咱们将经过解析从点击App图标到App打开这个流程和其中的一些相关细节。
为了理解RN是怎么在背后建立View的,咱们先须要解释一些基础概念:
理解了上面的一些基础概念,让咱们来看下打开App时,每一步发生了什么:
用户点击App的图标
UIManager线程:加载全部的Native库和Native组件好比 Text、Button、Image等
告诉Js线程,Native部分准备好了,Js侧开始加载main.bundle.js,这里面包含了全部的js和react逻辑以及组件。
Js侧经过Bridge发送一条JSON消息到Native侧,告诉Native怎么建立UI。值得一提的是:全部通过Bridge的通讯都是异步的,而且是打包发送的。这是为了不阻塞UI,举个栗子:
Shadow线程最早拿到消息,而后建立UI树
而后,它使用Yoga布局引擎去获取全部基于flex样式的布局,而且转化成Native的布局,宽、高、间距等。。
以后UIManager执行一些操做而且像这样在屏幕上展现UI:
这些就是启动App是的主要步骤。
RN基于这个架构有如下优势:
可是,有优势确定也会有缺点。下面咱们介绍一下可以解决现有缺点的新架构:Fabric。
咱们已经讨论了RN的当前架构,是时候说一下其中的缺陷。能够看一下Facebook的React团队负责人在她博客里提到的。
当前架构的缺点是:
不过不要误会,Facebook本身也正在使用React Native开发各类app,服务百万级的日活用户。同时也有其余有名的公司在生产环境中使用基于当前架构的RN,好比Wix、Bloomberg、Tesla、Zynga等等。
RN开发团队正着手去解决上面提到的缺点。
这是以前的RN架构:
这是新的架构图:
让咱们来解释一下这些新的概念:JSI,Fabric,Turbo Modules,和 CodeGen。
JSI(将会替换Bridge) -- 为了让JS和Native可以互相感知。将再也不须要经过Bridge传输序列化JSON。将容许Native对象被导出成Js对象,反过来也能够。两侧也会导出能够被同步调用的API。实际上,架构的其余部分都是基于这个之上的(Fabric,Turbo Modules等,这些下面会解释)
Fabric -- UIManager的新名称,将负责Native端渲染。和当前的Bridge不一样的是,它能够经过JSI导出本身的Native函数,在JS层能够直接使用这些函数引用,反过来,Native层也能够直接调用JS层。这带来更好更高效的性能和数据传输。
Turbo Modules。记得上面的Native组件吗?Text、Image、View,他们的新名字叫Turbo Modules。组件的做用是相同的,可是实现和行为会不一样。第一,他们是懒加载的(只有当App须要的时候加载),而如今是在启动时所有加载。另外,他们也是经过JSI导出的,因此JS能够拿到这些组件的引用,而且在React Natvie JS里使用他们。尤为会在启动的时候带来更好的性能表现。
CodeGen -- 为了让JS侧成为两端通讯时的惟一可信来源。它可让开发者建立JS的静态类,以便Native端(Fabric和Turbo Modules)能够识别它们,而且避免每次都校验数据 => 将会带来更好的性能,而且减小传输数据出错的可能性。
Lean Core -- 是对React Native库架构的变化。目的是减轻lib的负担,并帮助社区更快地解决更多pull request。Facebook正在把库的某些部分拆分出来,经过关注Github就能够看出他们在这方面的行动了。好比这个:
顺便一提,这里有个例子,你能够在Chrome里尝试一下,这也是JSI如何工做和导出对象的灵感来源:
在Chrome里打开开发者界面,而后输入console.log,回车。你将看到native code。这说明console.log实际上是一个Native的函数。
接下来咱们再对比一下使用新架构,App启动的流程是怎么样的。
用户点击App的图标
Fabric加载Native侧(没有Native组件)
而后通知JS线程Native侧准备好了,JS侧会加载全部的main.bundle.js,里面包含了全部的js和react逻辑+组件
JS经过一个Native函数的引用(JSI API导出的)调用到Fabric,同时Shadow Node建立一个和之前同样的UI树。
Yogo执行布局计算,把基于Flexbox的布局转化成终端的布局。
Fabric执行操做而且显示UI==>
为了完成整个流程,咱们几乎作了一样的事情,可是没有了Bridge,如今咱们能够有更好的性能,咱们能够用同步的方式进行操做,甚至能够对UI上的同步操做进行优先级排序。启动时间也将更快,App也将更小。
因此,咱们何时能够上手使用这些东西?
能够在Github上关注它们各自的更新状况:
按理说,大多数的更改将逐步完成,并有但愿在2019第四季度或2020第一季度发布。
部分参考文档,便于更深入地理解: