Weex & ReactNative & JSPatch

迁移一批老文章到掘金css

在微博上看到一篇绝赞的文章html

Weex&ReactNative对比前端

绝对值得强烈推荐,我想写这篇文章的缘由就是由于看了这篇文章以为太棒了!前一阵子我本身确实有比较深刻的拆解分析ReactNative的源码,一连写了三篇源码分析,当Weex开源的那一天,我也第一时间run起了demo,第一时间感觉了这个东西,不少的新奇!不少的惊喜!vue

因为时间精力所限,我一直没有深刻的去拆解分析weex,仍是比较初步的了解和使用,因此一直没准备动笔写一篇对比类的文章,直到我今天看到了这篇文章,基于对RN的理解,看到了做者这么深入的从方方面面很是多的角度对比分析了两者,简直产生了好多共鸣!虽然我不了解weex,可是RN的痛点仍是至关至关认同的~哈哈哈哈react

因而才产生了今天的blog。ios

而且在这基础上,我还想对比一下iOS 与 JSPatch的这套框架,由于不管weex也好rn也好,他们的思路或许一脉相承思路同源,可是和JSPatch这套方案比,那还真是彻底不一样的两个世界,这两个世界差别之大,但又能实现一样的热更新功能界面,对比一下真的颇有意思!git

Weex&ReactNative对比

这两者之间的对比我相信,读过做者原文的能学到不少,这里我就不重复啰嗦相同的内容了,不过我仍是想以标注的形式,对于那些对比差别点我仍是想说说个人一些我的的见解^_^github

(后面的内容,竖线+灰色文字是原文,底下是个人见解)web

JS引擎:算法

weex使用V8, ReactNative使用JSCore

这一点和做者交流确认了,iOS上weex依然使用JSCore而在安卓上weex使用了V8。

其实为何会这样也是有缘由的,安卓ReactNative虽然使用了JSCore,但这个JSCore不是系统源生的,而是直接打入app包里的WebKit库,这也是为啥安卓项目引入RN包大小会增大4~5M的缘由,ReactNative在iOS上JSCore是系统自带的,彻底没法打入app包内,因此iOS的包大小,引入RN后变化并无那么夸张。

来到了weex,反正安卓RN都是彻底本身植入进去的一整个JSCore,那不如把JSCore换成最新的V8引擎,可是iOS就不一样了,iOS继续使用系统自带的JSCore仍是方便的,系统自带的不用白不用,别浪费了,否则APP包凭空再多个4~5M,这也是个大槽点哈哈

vue vs react

react模板JSX学习使用有必定的成本 vue更接近经常使用的web开发方式,模板就是普通的html,数据绑定使用mustache风格,样式直接使用css

我是iOS开发哈,前端领域我不是很了解,我是看原文评论里,不少人说vue用起来更爽,我还没深刻使用,可是我一个iOS客户端写React和JSX仍是有点痛苦的╮(╯_╰)╭,不过值得说的是即使使用了vue,据说weex依然重现了react的virtual dom以及v dom diff算法,做为渲染性能上的保证,据说哈,我不懂,但愿更多的前端大神给我解惑

布局

二者实现了flexbox的相同子集(都使用了FaceBook的代码解析),基本没有区别

哈哈都使用了FaceBook的代码解析,weex不愧是站在巨人肩膀上的~,顺带FlexBox算法这个仍是好多都在用,聚划算的LuaView在用(lua的flexbox算法),fb的AsyncDisplayKit Layout在用,我其实对这个没啥好吐槽的,惟一只有一点

我是一个客户端开发,对于源生客户端开发来讲,flexbox布局产生的页面层级太多了╮(╯_╰)╭,虽然weex和ReactNative,实际上都是纯native的界面渲染,但即使是native代码,View层级多了依然会带来些许性能问题

而FlexBox的排版就产生了不少这样的空UIView层级容器.这一层面实际上是能够优化的,布局用的View容器其实不用驱动UIManager亲自绘制,不知道是否是我把问题想简单了,你们能够看一下这图,一个很简单的页面对于native来讲,撑死了每一个图片是一层完事,可是换成了flexbox,层级就变成了这样

图1

其实我却是有个解决办法,就是不之前端的布局思路去作js脚本驱动native绘制,而是以客户端的思路,依然用js脚本驱动native绘制

这种思路的老前辈就是早已成熟3~4年的cocos2dx-lua,那种动态脚本更新整个游戏app,动态更新功能不是个新技术哈~思路早就有。

这种思路其实也是JSPatch的体现,JSPatch虽然写的是JS代码,可是全都要以native的编写代码风格,native的api使用风格去写代码,最终写出了跟纯native如出一辙的功能界面。(相比较cocos2dx whole nativebridge的方案 JSPatch 的runtime bridge方案极度的轻便的多!)

页面开发

weex提供了一个playground,能够方便的预览正在开发的页面

ReactNative开发一个页面,须要创建一个native工程,而后编译运行

这一点也是一个最大的感触,weex是一套解决三端,安卓,iOS,wap的解决方案,而ReactNative仿佛在facebook创造它的时候,没有为他考虑太多的wap,据说携程在使用RN的时候,先有ReactMix,后有Moles框架,都是在RN之上,在封装了一层统一wap,iOS,安卓三端的庞大框架,如今好了weex从一开始设计的出发点,就从3端去考虑了

既然支持了wap,wap也是一个环境,天然写功能页面的时候,彻底能够不用Android Studio,不用Xcode,开一个浏览器跑起来wap的效果,也就是wap playground,等wap调的差很少了,再搭建native环境去细致跑

打包

ReactNative官方只能将ReactNative基础js库和业务js一块儿打成一个js bundle,没有提供分包的功能,须要制做分包打包工具

weex默认打的js bundle只包含业务js代码,体积小不少,基础js库包含在weex sdk中

这个是个大吐槽!RN打出来的包,除了咱们本身写的index.ios.js之外,把一整个React基础JS库全打进包里了,确实这部分彻底能够内置app的,否则太浪费动态更新的流量了

扩展性

组件的扩展上,weex和ReactNative具备同样的能力

三方库的接入上,weex对网络,图片,统计等常见的用户可能想本身定制的功能,提供了相应的适配接口,能够由用户方便的定制,ReactNative须要本身修改源码

这块虽然不了解weex,但以为ReactNative作的实在是太赞了,全部RN的native底层,都是一个个的模块Module,彻底解耦,随意灵活扩展插拔移除,并且支持开发者自行构建彻底本身的Module,不管是界面仍是数据网络接口。

我常常说的一句是,ReactNative实际上是一个能够任意扩展支持的框架,你down下来的源码,你发现实现不了的功能,扩展一下,妥妥没问题,你down下来的源码,你发现性能有问题?很卡?(没错我说的就是listview!)我去本身扩展一个啊~iOS基于tableview本身重写一个带重用cell的RNTableview~安卓基于recycleview,重写一个哈?我始终认为,RN是一个思路,不是一个死的框架

Moudle方法调用线程

weex 能够经过注解标注是否在UI线程执行

ReactNative在native_modules线程执行

这一点和做者交流了一下,安卓是这样的,可是iOS不是,iOS里面,RN每个native_modules线程同样能够支持标记控制,只须要重写module的methodQueue方法,return gcd队列的mainqueue就行了,RN的module线程控制源码就是dispatch_async,gcd的queue通常默认用class那么字符串建立,因此默认是随机线程惟一队列,但若是指定async到mainqueue,是能够直接切换到主线程的

//RCTClipboard类的源码
- (dispatch_queue_t)methodQueue
{
  return dispatch_get_main_queue();
}
复制代码

ListView Android

ReactNative目前采用scrollView使用,有一些性能问题

weex使用recyclerview实现,性能稍好

这个刚才就提到了的一个大吐槽!RN的ListView!RN的ListView是彻底基于scrollview封装的,一旦数据够多,是彻底没有重用的,业务中若是真的对listview性能痛苦不堪,而且RN提供的一些JS层面的优化性能的属性还不能知足需求,那是真的得彻底从新本身封装一个基于native重用的ListView,不少人在使用RN的时候估计也都不能忍ListView而后本身封装了吧?这下好了,weex帮你作了

2016.7.27补充

ListView缺乏重用机制是一个本质上的问题

无数的人在和我强调ListView没有问题,我这里说的是重用机制,重用机制ListView是彻底没有的,因此ListView在使用上推荐使用分页的方案,而不是无限制持续上拉加载更多,无上限的持续加载成百上千的Cell,这一点才是本质层面的问题

ListView因为这个底层实现的本质,因此在使用上推荐用分页的方法,不管是20个一屏,仍是30个一页,实际上没啥区别,依然是没法不封顶的增长数量,在一些常规使用方法下ListView有一些基本的优化选项,能够增长表现力,但这改变不了功能上缺失的本质

facebook官方文档中文翻译-性能优化

这是一个频繁出现的问题。由于iOS配备了UITableView,经过重用底层的UIViews实现了很是高性能的体验(相比之下ListView的性能没有那么好)。用React Native实现相同效果的工做仍正在进行中,可是在此以前,咱们有一些可用的方法来稍加改进性能以知足咱们的需求。

以上是FaceBook官方的原文翻译,ListView有没有问题天然能看到。不用我多说了。。。

顺带Git上已经有UITableView的RN封装

github react-native-tableview

粗略看了下源码实现,跟我脑海中的那套方案一致,每个cell内部是一个rootview,能够经过initParams传入不一样数据,进行reload渲染,cell天然进入native OC的重用池,(我太偷懒啦,有了一点思路,一直没亲自实现)

工具链

卧槽,我要继续提一句,weex不亏是站在巨人肩膀上的,开发RN的时候其实有不少痛点,调试界面的时候,我须要全局加框,来查看flexbox布局是否正确,打包的时候我彻底得本身从新开发分包或者diff包的工具,从而作到增量更新。

当我第一天使用weex的时候,就看到了那个devTools,那个可爱的小button,这可比RN的command + R的能力强大得多,用两个字评价就是贴心!

说点我本身的对比见解

我仍是想说

站在巨人的肩膀上看的更远!

其实在我看来(我不太懂前端,我以为从React.JS到Vue.JS,前端层面weex和rn的差别应该很是大),在native层面,也就是如何用js写出来的确是纯native界面这个原理上来讲,Weex与ReactNative,思路同源,一脉相承,我以为差别彻底不大,原理是共通的,甚至若是扔掉了JSCore换成C++的luaengine,是否是跟LuaView都原理和核心思想是一致的呢?(luaview也是flexbox用lua写布局,最终是native渲染,不过我是真的没亲自跑过luaview的代码,但我2年前是作cocos2dx-lua的,很是了解lua动态更新app的机制)

可是facebook作出来的RN,咱们在使用上确实是有不少的吐槽,这些吐槽彻底不是RN作不到

  • 你说RN作不到封装一个打包+diff工具吗?不可能,咋可能作不到
  • 你说RN作不到开发一个更加贴心,更加酷炫的devTools和那个可爱的小button吗?固然不可能,扩展一下分分钟支持
  • 你说RN真的作不到更优化ListView?不少第三方的作出来了,facebook咋可能作不到
  • 你说RN真的作不到统一wap?传说中的携程的moles都是基于RN而后再扩展的一套牛逼的大框架,说明设计上没啥不可能作到的

RN自己是一套很是牛逼很是灵活而模块扩展式设计,自然支持你任何开发者去补充RN,去扩充RN,这些都不是RN的不足。

若是把ReactNative比做是Linux系统,不懂的人会以为这也太难用了吧?看视频软件须要单独配置,去yum包去命令行安装配置一大堆,装各类软件都得命令行弄一大堆(好久之前上学的时候纯小白对Linux的认知),但不能说Linux系统是不能看视频解码小电影的╮(╯_╰)╭

那么Weex就很人性化的针对痛点,作了更多改善上的事情,更贴心,更易用,更强大,但又不失灵活,开源,扩展都还在(这里没有引伸windows缺点的意思)

我甚至能有一种感受,必定是深入的使用过RN,真的了解了RN的痛点,才驱动作出这样一个贴心的项目

iOS 平台独有的 JSPatch 动态更新完整功能

这里我要说一点就是,JSPatch如今不少人是拿他当HotPatch,进行热修复线上bug去用的,可是他得益于OC极其强大牛逼的运行时,超级灵活的反射机制,不像安卓的hotfix,可能受限于设备,受限于系统,总之反射机制不能彻底发挥做用。

  • JSPatch能够修改任何已经用OC写好的代码从而实现hotfix
  • JSPatch能够动态建立任何本来OC代码没有写没有实现的类
  • JSPatch能够对任何类(不管OC已有代码的类,仍是JSPatch动态建立的类)建立任何新的方法,任何OC本来没有写好的方法
  • JSPatch能够调用任何存在类,存在的方法,哪怕这条调用语句并无预先被OC写好

从上面的描述咱们能够看出来,JSPatch毫不仅仅能够用来HotFix,而是能够用来构建全新的功能,而且实现一整个功能模块的动态更新!

而且JSPatch的灵活无人能比

说句实话JSPatch得益于牛逼无敌的OC,runtime,他的灵活能力,是ReactNative&Weex这个方案思路远远不能比的。

  • 例子一

举个最简单的例子,RN与Weex,对于微信支付这种很native的模块,或许都是采用预先在native代码里写好了实现,最后让JS去调用(不管是开发者本身扩展的仍是系统扩展的),这个东西就叫jsbridge,但这个bridge很普通,你写了微信支付的jsbridge,那你的js就有了微信支付的能力,你写了支付宝支付的jsbridge,那你的js就有了支付宝的能力,你写了iOS平台的IAP的jsbridge,那你的js就有了IAP的能力,若是你没写咋办?你的JS就办不到,要知道,扩写这些jsbridge,都是须要发版的,都是不能动态更新的。

换句话说,若是一开始使用RN的app只开发了支付宝的支付功能,写好了支付宝的jsbridge,因而发版上线了,等某一天忽然想接入苹果的applepay,那么只有一个办法,那就是从新发版,从新写好了applepay的jsbridge,再次提交苹果审核(我举了个系统库的例子,但意义能够扩展一下)

可是对于JSPatch来讲,JSPatch也是一套基于JSCore的bridge,可是牛逼就牛逼在JSPatch不是这种常规的normal jsbridge,而是runtime jsbridge,runtime的特色就是实现没有被任何oc代码预先写好的功能,同时还能修改已经被OC代码预先写好的功能!

  • 例子二

若是整个APP都是RNorWeex包一个壳子,全部功能都是js写的,那么若是不须要更新jsbridge,那么确实能够实现,修改任何功能模块,写新的功能模块,均可以用RNorWeex进行热更新,彻底不发版。

可是我相信,至关多的APP都是部分界面保留原有工程的native,部分界面,部分新界面采用RNorWeex(那些已经成熟的大app必定是这样的,不可能推翻重写)

那么问题来了,RN能更新用RN写的界面,RN能更新那些本来native的界面吗?答案是不行,JSPatch能够。RN能够开发一整个新功能界面,动态更新到app上,可是这个新功能界面怎么打开呢?办法有一个,app内有一套URLRoute的路由机制,而且辅助以云端可控的路由配置表,那么确实能够改变某些位置本来的界面跳转,从而跳转打开全新的RN界面,实现了新RN界面的动态更新,可是JSPatch就不须要URLRoute这套全局跳转的辅助机制帮忙,JSPatch彻底有能力更改任何已经由OC写好的代码,随意的改变跳转到新界面,随意的增长新按钮,不改变旧界面就把新界面打开!

阿里的Wax

与JSPatch能力和机制相似的还有阿里的Wax

Wax本是好久之前国外的大神编写的一套用Lua写OC的动态框架,可是这个框架太老了,老到尚未支持苹果64位就没人维护了,年代过久远了

大众点评的大神在Wax的基础上融入了运行时,变成了WaxPatch,但这年代也好久远,也是在没有支持64位的时候就不维护了。

直到去年10月,阿里宣布接管维护了Wax,而且大量扩展了海量功能,由于之前的wax也好waxpatch也好,支持的动态runtime能力还特别少。

不过都是纯iOS平台,毕竟这种思路和玩法彻底依托于无敌的OC Runtime

JSPatch 福祸相依,优劣共存

和JSPatch的做者@bang哥学习以及交流了不少动态更新方面的见解,bang哥最近也在酝酿一篇大做,专程去对比JSPatch与ReactNative的对比。

bang哥的见解

对比 学习成本 接入成本 热更新能力 开发效率 性能体验
Weex&RN 高,跨平台
JSPatch 中,不跨平台

总的来讲,JSPatch在学习成本,接入成本,热更新能力上占优,而 React Native 在开发效率和跨平台能力上占优,你们能够根据需求的不一样选用不一样的热更新方案。JSPatch 目前仍在不断发展中,欢迎参与这个开源项目的开发。

原文还没发布,等到发布了我必定第一时间补上原文连接。

个人一些补充:

  • 学习成本:

这实际上是对native开发人员来讲的,JSPatch全部的API,全部的写法,全部界面的布局,都是纯native开发人员最熟悉的,只是须要略微熟悉下从OC变JS的转变(最基础的js语法)(甚至有一些不是太智能的oc直接转js的工具),以及JSPatch的一些独特规定,对于native iOS开发人员来讲(就是我啦),学习css+html式的布局,理解flexbox(忍受flexbox那层级的吐槽),其实远没有直接按着native的思惟方式写JSPatch方便。

ReactNative&Weex的方案更贴近web开发人员,尤为是熟练掌握React和Vue的,可是当面临自定义扩展native能力也就是bridge开发的时候,其实仍是须要native代码能力,而且视你的扩展需求不一样,可能须要比较深的native能力。

因此从我一个native开发人员的角度来说,JSPatch学习成本低不少

  • 接入成本

你能想象 JSPatch的核心代码,不算边角扩展,全部源码只有2个文件吗?jspatch.jsJPEngine.h.m

  • JPEngine.h.m 只有区区1700行代码!
  • jspatch.js 只有区区200行代码!

这接入成本可想而知啊,下源码,扔进工程,完事啊~哈哈哈哈哈

  • 热更新能力

前面解释的够多了,在iOS平台上,JSPatch其runtime能力,真的是不管weex仍是ReactNative都是远远没法比拟的

  • 开发效率

确实Weex & ReactNative的辅助开发工具超级多,而且HTML+CSS式的界面布局,熟练了之后开发真的是太快了╮(╯_╰)╭

JSPatch仍是native的开发方式,辅助工具也开发了不少,你们能够细看JSPatch的Github和bang哥的Github和博客,但效率上我以为仍是比不上的╮(╯_╰)╭

  • 性能体验 bang哥的评价两者都是高,我以为两者差别不大,但非要说个优劣,我提到过flexbox的层级问题,即使是纯native开发搞出如此多的层级,也是会有性能损耗的,但这个点可能没那么关键,性能损耗没那么严重。两者最终都是纯native的效果与渲染,与触摸交互,因此,都给了个高的评分

我用JSPatch也遇到一些坑

JSPatch目前在使用上会和webview有必定的冲突,若是有须要动态用jspatch写一个含有webview的页面的时候,会有略微的麻烦,和不稳定因素,在GitWiki上有明确介绍了如何在JSPatch里面使用webview,好比初始化的时候先于JSPatch构建一个Webview而后在销毁啊,好比js建立webview记得须要十分当心的使用一个performInOc的api啊,不要按着经常使用方法使用,还有就是不稳定,个人case是某一些特殊的业务场景下,会偶现crash(很低几率,可是频繁操做能够复现)

JSPatch与ReactNative的内存控制差别

  • JSPatch在OC与JS交互的时候,是支持直接把一个OC对象,一个界面,一个model,直接传给JS上下文里面的,这个OC对象会所以引用计数+1,而且随着JS上下问的垃圾回收机制,对这个OC对象进行引用计数的额外控制,在JS上下文内是没法去查看这个OC对象的,可是却能够指定任何OC对象本来的方法,而后发送回OC环境去操做这个OC对象。

  • RN在OC与JS交互的时候,是彻底不支持传递任何OC对象的,全部能在JS与OC中间传递的,必定是能够被json化,字符化的内容,数字,字典,数组,字符串,因此RN专门有个RCTConvert类去专门处理,json的序列化model化,反序列化反model化。那么RN是如何经过JS去控制一个纯OC的界面View呢?是经过viewTag,JS控制的每个界面效果,都是传过来一个tag,让native建立,让native修改,native会储存住这些tag到一个hashmap里,这样JS才可以不直接传递OC对象,而是传递一个数字,从而控制OC对象

两者的实现差别,是会形成一些底层运行差别的,OC与JS对象只传递JSON其实就保证了,JS上下文的内存与OC上下文的内存彻底没有互通,各自的内从各自控制,JS是一套垃圾回收机制,而OC是一套引用计数机制。

JSPatch将两者进行了互通,这些互通的对象内存管理则是一套,又有引用计数控制,又有JS的垃圾回收,当JS的垃圾回收,而且iOS的引用计数归0,才会销毁。

这里没有优劣之分,JSPatch在双内存控制机制下,也是能够正常work没有问题的,RN&Weex的这套机制,内存上简单清晰,不过这都是底层实现的问题,上层使用,都是没问题的

相关系列文章

相关文章
相关标签/搜索