一.历史:React Native 从开始到现在

React Native 的定位是通过 React 构建原生 App:

A framework for building native apps with React.

具有 5 大特性:

  • Create native apps for Android and iOS using React:用 React 创建 Android、iOS 应用

  • Written in JavaScript—rendered with native code:写的是 JavaScript,实际渲染的是 Native 界面

  • Native Development For Everyone:基于平台无关的基础组件开发,就能获得平台原生体验

  • Seamless Cross-Platform:无缝过渡,Native 代码能够包装成 React Native 可用的组件

  • Fast Refresh:改动立即生效,拥有 Web 一样的开发速度

那么,有 2 个问题:

  • 为什么要用 React(或者说用 JavaScript)写 Native 应用?源动力是什么?

  • 为什么以这种方式跨平台,而不是 WebView?

探索思路

之所以用 React 写 Native 应用,有 2 方面原因:

  • React 自身的优势:声明式视图定义带来的 UI 可预测性、组件化机制下的复杂度拆解等

  • Web 开发的优势:快速迭代、快速反馈、快速开发

Native 用上 React 的话,也能获得 React 的种种好处。当然,这只是一方面,背后的真正源动力是希望 Native 开发能像 Web 一样 move fast

而对于第二个问题,要从 React Native 的由来说起

实际上,Facebook 尝试过 3 种思路:

  • WebView:由 Native 提供 Webview 容器,业务用 Web 技术来开发

  • Porting React to native:把 React 移植到 Native 实现

  • Scripting native:通过 JavaScript 调用 Native API

不利用低成本的 WebView 方案跨平台,是因为受限于 Web 技术,体验无法与 Native 相提并论,最终因性能和扩展性没有达到预期而作罢

把 React 移植到 Native 是个不错的思路,但只能获得 React 自身的一些好处(不包括 JavaScript 世界的 React 繁荣生态),并且无助于 Native 的 move fast,因为 Native 还是纯 Native

相比之下,React Native 通过 JavaScript 调用 Native API 是一个两全其美的方案,既能让 Native 用上 React(及 JavaScript 的繁荣生态),也能拥有 Web 的开发速度,因为写的和实际执行的都是 JavaScript,Native 仅提供视图渲染能力及平台特定能力

发展历程

React Native 诞生于 2013 年的 Facebook 内部黑客马拉松(hackathon)

2015 年 1 月的 React.js Conf 上,这个内部项目首次公布,并在 5 月的 F8 Conference 上正式开源。最初只支持 iOS,同年 9 月支持了 Android

2016 年提供的 Microsoft UWP 和 Samsung Tizen 支持,意味着 React Native 从移动端走向了 PC(Win 10)、游戏机(Xbox One)、手环(Gear Fit 2)、智能电视机(SUHD)甚至全息眼镜(HoloLens)

2018 年 6 月启动了架构升级计划 Fabric,重构线程模型并简化 React Native Core,以更好地支持 Native & React Native 混合 App

2019 年 7 月迎来 JavaScript 引擎级性能提升,将 Android 平台之前使用的 JavaScriptCore 替换成 Hermes

P.S.关于 React Native 发展史的更多信息,见React Native 简史

二.架构:原来,你是这样的 RN!

写的是 JavaScript,实际渲染的是 Native 界面

因此,从非常高的视角来看,可以这样理解 React Native 技术(或者说 Scripting Native 方案):

JavaScript层
---------------------------------
???
---------------------------------
Native层

关键点在于:中间是什么?上下两个世界是怎样联系起来的?

架构设计

在 React Native 里,中间是 Bridge 层,通过消息通信将 JavaScript 世界与 Native 世界联系起来

具体的,Shadow Tree 用来定义 UI 效果及交互功能,Native Modules 提供 Native 功能(比如蓝牙),二者之间通过 JSON 消息相互通信:

Bridge 层是 React Native 技术的关键,设计上具有 3 个特点:

  • 异步(asynchronous):不依赖于同步通信

  • 可序列化(serializable):保证一切 UI 操作都能序列化成 JSON 并转换回来

  • 批处理(batched):对 Native 调用进行排队,批量处理

P.S.关于 React Native 架构的更多信息,见React Native 架构一览

线程模型

React Native 中主要有 3 个线程,分别是:

  • UI Thread:Android/iOS(或其它平台)应用中的主线程

  • Shadow Thread:进行布局计算和构造 UI 界面的线程

  • JS Thread:React 等 JavaScript 代码都在这个线程执行

此外,还有一类 Native Modules 线程,不同的 Native Module 可以运行在不同的线程中(具体见Threading

启动过程

整体上,启动过程分为初始化 Bridge 与执行业务代码两部分,对应图中上下两部分:

渲染机制

首次渲染时(图中自右向左的流程),JS 线程将视图信息(结构、样式、属性等)传递给 Shadow 线程,创建出用于布局计算的 Shadow Tree,Shadow 线程计算好布局之后,再将完整的视图信息(包括宽高、位置等)传递给主线程,主线程据此创建 Native View

用户交互时(图中自左向右的流程),则先由主线程将相关信息打包成事件消息传递到 Shadow 线程,再根据 Shadow Tree 建立的映射关系生成相应元素的指定事件,最后将事件传递到 JS 线程,执行对应的 JS 回调函数

架构演进

最初的设计也带来了一些限制:

  • 异步:无法将 JavaScript 逻辑直接与许多需要同步答案的 Native API 集成

  • 批处理:很难让 React Native 应用调用 Native 实现的函数

  • 可序列化:存在不必要的 copy,而不是直接共享内存

这些问题在 Native + React Native 的混合应用中尤其突出,因此,2018 年 6 月提出了大规模的架构升级计划:

具体包含 3 点重大改动:

  • JavaScript 层:引入 JSI,允许替换不同的 JavaScript 引擎

  • Bridge 层:划分成 Fabric 和 TurboModules 两部分,分别负责 UI 管理与 Native 模块

  • Native 层:精简核心模块,将非核心部分拆分出去作为社区模块独立更新维护

Fabric 期望简化渲染流程中复杂的跨线程交互,允许 JavaScript 直接控制高优先级的 UI 操作,甚至允许同步调用(应对列表快速滚动、页面切换、手势处理等场景)

TurboModules 允许按需加载 Native 模块,并在模块初始化之后直接持有其引用,不再依靠消息通信来调用模块功能

P.S.关于 React Native 架构升级的更多信息,见React Native 架构演进

三.生态:Learn once, write anywhere ?

React Native 最初的愿景是learn once, write anywhere

It’s worth noting that we’re not chasing “write once, run anywhere.” Different platforms have different looks, feels, and capabilities, and as such, we should still be developing discrete apps for each platform, but the same set of engineers should be able to build applications for whatever platform they choose, without needing to learn a fundamentally different set of technologies for each. We call this approach “learn once, write anywhere.”

(摘自React Native: Bringing modern web techniques to mobile

应用生态

平台支持上,目前(2019/9/21),除官方提供的 Android、iOS 支持外,社区还提供了UWPTizenWebMacApple TV,甚至微信小程序等支持

P.S.更多支持平台,见Out-of-Tree Platforms

企业应用方面,除 Facebook 外,React Native 在腾讯、百度、京东等大规模企业中都有所应用:

工具生态

React Native 发展至今的 4 年里,工具生态也有了一定程度的发展:

P.S.关于 React Native 生态的更多信息,见Exploring React Native Ecosystem – Tools, backend, database and best libraries

比起积淀深厚的 Android、iOS 技术生态,React Native 生态尚处于较低成熟度的阶段,因而面临与 Native 基础设施集成、跨语言栈调试等难题。但无论怎样,Learn once, write anywhere 的愿景在路上,正向我们赶来

参考资料

1000 千米高空俯瞰 React Native的更多相关文章

  1. React Native初探

    前言 很久之前就想研究React Native了,但是一直没有落地的机会,我一直认为一个技术要有落地的场景才有研究的意义,刚好最近迎来了新的APP,在可控的范围内,我们可以在上面做任何想做的事情. P ...

  2. React Native之 ScrollView介绍和使用

    前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...

  3. React Native props & state

    今天又敲了一丁点代码,看了一下props和state的用法 原本以为state只是一个状态,但是又阅读了一下原文,才知道state是一组状态,这些状态是开发者自己定义的,都统一在state这个大类底下 ...

  4. React Native 的ES5 ES6写法对照表

    模块 引用 在ES5里,如果使用CommonJS标准,引入React包基本通过require进行,代码类似这样: //ES5 var React = require("react" ...

  5. React/React Native 的ES5 ES6写法对照表

    //es6与es5的区别很多React/React Native的初学者都被ES6的问题迷惑:各路大神都建议我们直接学习ES6的语法(class Foo extends React.Component ...

  6. React/React Native 的ES5 ES6写法对照表-b

    很多React/React Native的初学者都被ES6的问题迷惑:各路大神都建议我们直接学习ES6的语法(class Foo extends React.Component),然而网上搜到的很多教 ...

  7. [转] 学习React Native必看的几个开源项目

    http://www.lcode.org/study-react-native-opensource-one/ http://gold.xitu.io/entry/575f498c128fe10057 ...

  8. React Native学习(八)—— 对接七鱼客服

    本文基于React Native 0.52 Demo上传到Git了,有需要可以看看,写了新内容会上传的.Git地址 https://github.com/gingerJY/React-Native-D ...

  9. 学习React Native必看的几个开源项目

    学习React native ,分享几个不错的开源项目,相信你学完之后,一定会有所收获.如果还没有了解RN的同学们可以参考手把手教你React Native 实战之开山篇<一> 1.Fac ...

随机推荐

  1. 一只简单的网络爬虫(基于linux C/C++)————开篇

    最近学习开发linux下的爬虫,主要是参考了该博客及其他一些网上的资料.网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息 ...

  2. Git上传本地仓库项目到gitee远程仓库(命令篇)

    前言:最近整理了一下自己之前的自学代码,包括一些练习的项目.发现有些杂乱,故想使用Gitte(码云)管理.加上不少公司使用Git,所以写了这篇文章记录. 如果我们本地有了项目,那么如何上传到码云上呢? ...

  3. 题目分享Q

    题意:给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大 分析:这可以说是换根法的裸题吧 首先考虑对一个给定的根如何计算,这应该是最简单的那种树形dp吧甚至可能都不算dp(好像 ...

  4. 数据源管理 | 基于DataX组件,同步数据和源码分析

    本文源码:GitHub·点这里 || GitEE·点这里 一.DataX工具简介 1.设计理念 DataX是一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL.Oracle等).HDF ...

  5. MODIS系列之NDVI(MOD13Q1)五:NDVI处理流程

    前言:(个人建议) 1.进行数据处理工作,由于通常数据量比较大.所以在个人电脑中,要将基础数据.不断增长的过程数据.结果数据等分门别类,使得简单易找. 2.将重要数据备份,因为在数据处理过程中,由于出 ...

  6. java基础篇 之 集合概述(List)

    list,有序集合,元素可重复 LinkedList:底层用链表实现,查找慢,增删快.为什么?? ArrayList:底层用数组实现,查找看,增删慢.为什么?? Vector:跟ArrayList一样 ...

  7. python学习之break和continue在for循环中的使用(案例:打印出10以内的偶数,并且只要前三个偶数)

    运行程序,break是整个程序都跳出 continue则表示跳过当前一次循环,然后继续执行循环

  8. 简单服务发现协议(SSDP)编程指导

    本文主要讲解如何使用ssdp进行编程,不涉及过多关于ssdp的理论知识 1. 前言   网上对ssdp理论介绍的一大把,缺乏从编程角度的一个指导,这里不会长篇大论ssdp理论,只是根据实际编码经验对用 ...

  9. SVN 报错问题

    svn: error: The subversion command line tools are no longer provided by Xcode ```. ## 问题分析 由于Mac绝大部分 ...

  10. Linux安装tomcat并部署JavaWeb项目

    前提条件: 安装tomcat前请确认一下信息: 系统安装了JDK,且JDK版本应与javaWeb所使用的JDK一致,具体操作可参见Linux下安装JDK. 打包了javaWeb的.war 文件,具体操 ...