一 为什么跨端动态化迫在眉睫

目前很多互联网大厂的移动端开发都在朝着跨端动态化方向发展。由于快速迭代开发或者对原生包体积要求严格,及其对资源成本的把控,实现跨端动态化迫在眉睫。我们先来看看 Native 原生开发的一些不足之处:

  • 1 原生开发周期时间长,审核周期长,会影响到需求发布和迭代效率,有些场景下会更加棘手,比如修复线上紧急 bug ,或者是频繁迭代一些开发需求。
  • 2 目前移动端主要的平台就是 Android 和 iOS,如果一款前端应用想要同时运行在两个平台的话,采用 Native 就需要双端各自开发一遍,这样无疑浪费了资源和提高了维护成本。
  • 3 Native 开发代码要打包在客户端包中,这样增加了包的体积,用户下载的时候,会下载更多的资源,轻量级的包会提高运营效率,而且 Android 和 iOS 应用平台也对包体积严格把控。

说到跨端化方案,首先想到的就是 React Native,为什么这么说呢? 我们往下看。

二 首当其冲的为什么是 React Native

React 在跨端领域也有一席之地,功劳来源跨端方案 React Native,简称 RN ,RN 是目前主流的动态化方案之一,是 Facebook 在 2015 年开源的 JS 框架 React 在原生移动应用平台的跨平台技术,支持安卓和 iOS 平台。

RN 的受欢迎并不仅仅是支持安卓和 iOS 平台,还有一个重要的因素就是动态化,那么这种动态化相比于原生客户端有什么优点呢?

RN 对于原生开发有着明显的优点:

  • 1 RN 是采用运行 React 的 JS 作为开发平台,这样可以让 web 开发者也能够参与到 Native 开发中来,还有就是 RN 让一套代码可以运行在两端,大大减少了开发和维护成本。
  • 2 RN 是采用原生渲染的,性能和体验仅次于 Native 开发。
  • 3 还有一点也是最重要的,就是 RN 是动态化的方案,也就是 RN 打出来的应用包,并不是和 Native 包绑定在一起发布的,而是在运行 Native 的时候拉下 RN 的包,这样一是减少了 Native 包体积,二是 RN 包可以随时发布,提高了迭代效率,也让一些线上问题能够快速解决。

近两年,也有一些兴起的跨端技术方案,比如 Flutter,阿里巴巴开源的 Rax 等,相比这些动态化方法,RN 也有一定优势:

  • 1 生态成熟,技术社区活跃,采用 React 语法,学习成本低。
  • 2 目前业界已经出现了很多成熟方案,比如京东的 JDReact 和美团的 MRN 等。

RN 是基于 React 框架开发的原生应用,React 凭借着 JSX 语法让使用者结合多种设计模式使开发变得非常灵活,React 是 JavaScript (简称 JS ) 框架,那么如果想要运行 RN ,那么就需要运行 JS ,在我们的影响中,JS 作为脚本语言运行到浏览器端,或者运行在 Node.js 中,那么如今却能够作为跨端方案运行到 Native 应用中,这是为什么呢?

原来能够让 JS 运行到 Native 中的法宝就是 JS 引擎,最常见的 JS 引擎就是 v8 ,v8 使用在 Chrome 浏览器和 Node.js 中,构建了 JS 运行时,能够执行 JS 脚本。那么接下来我们就来看一下 RN 中的 JS 引擎。

三 JS 引擎让跨端动态化成为可能

V8 引擎简介

计算机本身并不能读懂编程语言,计算机只能读懂二机制文件,但是为了能够让编程语法能够让计算机读懂,就必须编译成二机制文件,这就是编译语言,比如 JAVA GO 等都是编译型的语言,编译型语法在编译成二机制文件后,会保存二机制文件,在运行时候,可以直接运行二机制文件,不需要重复编译。

还有一类语言,不需要编译成文件,而是需要通过解释器对语言进行动态解释和执行,这类语言就是解释型语言,比如 Python,JS 等。如下图就是两种类型的语言执行过程:

编译型语言启动需要编译成二进制文件,所以启动速度会比很慢,但是执行的时候是直接使用编译好的二进制文件,所以执行速度会快一些。

但是相比解释型语言,启动会很快,但是执行时候,需要通过解释器解析语法树,变成中间代码,执行字节码,这样就浪费了时间,使得执行速度会变慢。

由于 JS 是解释型语言,它的执行需要宿主环境提供,转成语法树 ,并且读懂语法树,转成字节码并执行的能力,v8 引擎的工作就需要有这些能力:

Parser:将 JS 源码转换成抽象语法树,什么是抽象语法?在计算机科学中,抽象语法树(abstract syntax tree 或者缩写为 AST),或者语法树(syntax tree),是源代码的抽象语法结构的树状表现形式,这里特指编程语言的源代码。

Lgniton:interpreter 解释器,负责将 AST 转换成指令字节码,解释执行指令字节码(ByteCode),解释器执行的时候主要有四个模块:内存中的字节码,寄存器,栈和堆。

TurboFan:compiler 编译器,通过 Lgniton 收集的信息,将指令字节码转换成优化汇编代码。

Orinoco:garbage collector 简称 GC,垃圾回收模块,负责将程序不需要的内存空间回收,提升引擎性能。

如上还有一个问题就是如果每一次都通过 TurboFan 将指令字节码转换成汇编代码,那么这样十分浪费性能。在 v8 出现之前,所有的 JS 虚拟机所采用的都是解释执行的方式,这是 JS 执行速度过慢的主要原因之一。

而 v8 率先引入了即时编译(JIT)的双轮驱动的设计(混合使用编译器和解释器的技术),这是一种权衡策略,给 JS 的执行速度带来了极大的提升。

那么 JIT 就是取编译执行语言和解释执行语言的长处,利用解释器对代码进行处理,对于频率高的代码进行热区收集,在之后指令字节码编译成机器码的时候,储存高频率的二机制机器码,之后就可以复用并执行二机制代码,以减少解释器和编译器的压力。

v8 通过优化后的工作流程如下:

知道了 v8 JS 引擎的工作流程之后,那么 RN 应用中用什么 JS 引擎呢?

RN 在 0.60 版本之前使用 JSCore 作为默认的 JS 引擎, JSCore 全名 JavaScriptCore ,JSCore 是 WebKit 默认内嵌的 JS 引擎,JSCore作为一个系统级 Framework 被苹果提供给开发者,作为苹果的浏览器引擎 WebKit 中重要组成部分。

所以在 iOS 应用中默认为 JSCore 引擎,这使得 RN 也用 JSCore ,但是 JSCore 没有对 Android 机型做好适配,在性能,体积,和内存上和 v8 有着明显的差别。

基于这个背景,RN 团队提供了 JSI (JavaScript Interface)框架,JSI 并不是 RN 的一部分,JSI 可以视作一个兼容层,意在磨平不同 JS 引擎中的差异性。

JSI 实现了引擎切换,比如在 iOS 平台运行的 JSCore ,在 Andriod 中运行的是 v8 引擎。

JSI 同样提供了抽象的 API 接口,定义了与各个 JS 引擎交互的接口。

在 JS 中调用 C 注入到 JS 引擎中的方法,数据载体格式是通过 HostObject 接口规范化后的,摒弃了旧架构中以 JSON 作为数据载体的异步机制,让 JS 和 C 相互感知。

明白了 RN 内部运转的背景之后,我们开始正式进入 RN 的世界。

四 走进 React Native 的世界

React Native 将原生开发的最佳部分与 React 相结合, 致力于成为构建用户界面的顶尖 JavaScript 框架。

React Native 开发和传统的 web 端 React 应用开发类似,并且都是 js 语言,使得 web 开发者上手 RN 开发特别简单。

在 React web 应用中,打包,部署到上线的产物,是一个 html ,css,js 文件的集合体,最后把这些产物放在服务器上就可以了。

但是在 RN 中,最后打包产物是一个 js 文件,叫做 jsbundle ,在 Native 端运行 RN 项目,本质上是远程拉取了 jsbundle ,并通过上述的 js 引擎运行当前 jsbundle,每次运行一个 bundle 就需要外层容器提供一个 js 引擎。

在 React 构建的应用为单页面应用,如果存在多个页面,可以通过路由的方式实现页面的跳转,在 RN 中,也有一些解决方案,通常的手段是一个 jsbundle 对应一个页面,或者是一个 jsbundle 对应多个页面,如下图所示:

如果采用,原生 RN H5 等融合的技术方案开发的话,单 jsbundle 对应单页面的方式比较适合,但是如果是 Native 作为外层容器,里面都页面都是 RN 的话,单页面多 bundle 也是一个不错的选择。

基础用法

知道了 RN 的本质之后,我们看一下 RN bundle 的注册,在 RN 中每一个应用都有一个入口文件,RN 中提供了注册根本应用的方法,那就是 AppRegistry,这一点和 React web 应用会有一些区别,web 应用中,主要依赖于 react-dom 中提供的 api ,但是在 RN 项目中,无需再下载 react-dom,取而代之的是 react-native 包。

我们先来试着注册一个 RN 应用:

import {AppRegistry} from 'react-native'
/* 根组件 */
import App from './app' 
AppRegistry.registerComponent('Root', () => <App />)

如上我们注册了 Root ,指向了组件 App。接下来就可以在 App 就可以正常开发了。

在浏览器端,可以用 DOM 标签或者组件,但是在 RN 中是没有 DOM 的,所以如果想要引入原生的视图组件,就必须从 react-native 中引入,下面我们就编写一下 App 组件:

import react from 'react'
import { View, Text } from 'react-native';
function App(){
    return <View>
       <Text> Hello,React Native! </Text>
    </View>
}

除了基础的视图容器组件之外,RN 还提供了一些移动端常用的组件,比如列表组件 ScrollView,SectionList 等。

事件

对于一些用户交互事件,RN 中也提供了对应事件组件载体,比如点击事件用的是 TouchableOpacity。 如下所示

function App(){
    /* 处理点击事件 */
    const handlePress = ()=>{}
    return <TouchableOpacity onPress={handlePress} >
        <Text> click </Text>
    </TouchableOpacity>
}

样式

在 RN 中,是没有 css 样式文件的,RN 中的样式就和 CSS IN JS 类似,都是通过 JS 来完成的,RN 提供了 StyleSheet 可以创建 style 对象,如下所示:

import { StyleSheet, View } from "react-native"
const styles = StyleSheet.create({
    container: {
        flex: 1,
        padding: 24,
        backgroundColor: "#eaeaea"
    }
})
function App(){
    return <View style={styles.container} >
        样式处理
    </View>
}

对于 RN 的基础使用,如果参考官方文档,学习成本不高,上手也很快。

弄明白 RN 的运行环境和基础使用之后,那么都知道 RN 最终的打包产物只是一个 js 文件,那么这个 js 文件是怎么运行到 native 应用中的,又是怎么和 native 应用进行交互的呢?

接下来文章中我们会对 RN 的原理进行探秘,探索一下 RN 内部运转的机制。

另一方面,现在的动态化方案已经不仅仅是 Android 和 iOS 双端,而是 Android ,iOS ,web ,小程序四端,我们通过 RN 进入到跨端动态化方案上来,研究一下以 React 做 dsl 四端动态化方案的现状与未来。

五 总结

本文从跨端发展现状,再到 RN 运转的本质 JS 引擎,再到 RN 的使用,讲述了移动端动态化的一个落地方案。 如果没有用过 RN 开发过 app 应用的同学,可以尝试跑一下基础 demo 。

以上就是React跨端动态化之从JS引擎到RN落地详解的详细内容,更多关于React跨端动态化JS引擎RN的资料请关注Devmax其它相关文章!

React跨端动态化之从JS引擎到RN落地详解的更多相关文章

  1. ios – React native链接到另一个应用程序

    如果是错误的,有人知道如何调用正确的吗?

  2. ios – React Native – 在异步操作后导航

    我正在使用ReactNative和Redux开发移动应用程序,我正面临着软件设计问题.我想调用RESTAPI进行登录,如果该操作成功,则导航到主视图.我正在使用redux和thunk所以我已经实现了异步操作,所以我的主要疑问是:我应该把逻辑导航到主视图?我可以直接从动作访问导航器对象并在那里执行导航吗?.我对组件中的逻辑没有信心.似乎不是一个好习惯.有没有其他方法可以做到这一点?

  3. 在ios中使用带有React Native(0.43.4)的cocoapods的正确方法是什么?

    我已经挖掘了很多帖子试图使用cocoapods为本地ios库设置一个反应原生项目,但我不可避免地在#import中找到了丢失文件的错误.我的AppDelegate.m文件中的语句.什么是使用反应原生的可可豆荚的正确方法?在这篇文章发表时,我目前的RN版本是0.43.4,而我正在使用Xcode8.2.1.这是我的过程,好奇我可能会出错:1)

  4. ios – React Native WebView滚动行为无法按预期工作

    如何确保滚动事件的行为与ReactNative应用程序中的浏览器相同?

  5. ios – React Native – BVLinearGradient – 找不到’React/RCTViewManager.h’文件

    谢谢.解决方法几天前我遇到了完全相同的问题.问题是在构建应用程序时React尚未链接.试试这个:转到Product=>Scheme=>管理方案…=>点击你的应用程序Scheme,然后点击Edit=>转到Build选项卡=>取消选中ParallelizeBuild然后点击标志添加目标=>搜索React,选择第一个名为React的目标,然后单击Add然后在目标列表中选择React并将其向上拖动到该列表中的第一个.然后转到Product=>再次清理并构建项目.这应该有所帮助.

  6. ios – React Native – NSNumber无法转换为NSString

    解决方法在你的fontWeight()函数中也许变成:

  7. ios – React native error – react-native-xcode.sh:line 45:react-native:command not found命令/ bin/sh失败,退出代码127

    尝试构建任何(新的或旧的)项目时出现此错误.我的节点是版本4.2.1,react-native是版本0.1.7.我看过其他有相同问题的人,所以我已经更新了本机的最新版本,但是我仍然无法通过xcode构建任何项目.解决方法要解决此问题,请使用以下步骤:>使用节点版本v4.2.1>cd进入[你的应用]/node_modules/react-native/packager>$sh./packager.s

  8. 反应原生 – 如何通过Xcode构建React Native iOS应用程序到设备?

    我试图将AwesomeProject应用程序构建到设备上.构建成功并启动屏幕显示,但后来我看到一个红色的“无法连接到开发服务器”屏幕.它表示“确保节点服务器正在运行–从Reactroot运行”npmstart“.看起来节点服务器已经运行,因为当我做npm启动时,我收到一个EADDRINUSE消息,表示该端口已经在使用.解决方法从设备访问开发服务器您可以使用开发服务器快速迭代设备.要做到这一点,你的

  9. 静音iOS推送通知与React Native应用程序在后台

    我有一个ReactNative应用程序,我试图获得一个发送到JavaScript处理程序的静默iOS推送通知.我看到的行为是AppDelegate中的didReceiveRemoteNotification函数被调用,但是我的JavaScript中的处理程序不会被调用,除非应用程序在前台,或者最近才被关闭.我很困惑的事情显然是应用程序正在被唤醒,并且它的didReceiveRemoteNotifi

  10. 如何为iOS的React Native设置分析

    所以我已经完成了一个针对iOS的ReactNative项目,但是我想在其中分析.我尝试了react-native-google-analytics软件包,但是问题阻止了它的正常工作.此外,react-native-cordova-plugin软件包只适用于Android,因此插入Cordova插件进行分析的能力现在已成为问题.我也没有Swift/ObjectiveC的经验,所以将完全失去GA的插入.有没有人有任何建议如何连接GoogleAnalytics的ReactNativeforiOS?

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部