从开始到现在,笔者接触RN已经接近半年,适逢各种变化的发生,于是,简单的遐想了一下RN的未来。
Airbnb在今年早些时候,宣布了放弃继续使用RN,并且发布了一篇“React Native at Airbnb: The Technology”的长篇博客,详细的讲了在airbnb中,使用RN的过程中,自己的总结的一些经验和一些痛点,鉴于国内网络环境的原因,笔者也简单的转载一下(限于笔者的英文水平,翻译不确切之处还请批评指正):
做得好的地方:
跨平台、统一的设计语言系统(DLS)、React(特别是组件体系、简单的生命周期和声明式的写法)、迭代速度、基础设施上的额外开销(如网络、设备信息、i18n等)、性能、Redux、以native为支撑(更强大的native能力)、静态分析、动画、js/React的开源、伸缩盒模型(基于yoga)、web端的合作。
做得不是那么好的地方:
React Native的不成熟:虽然rn发展得很快,但是有欠成熟的它在某些具体的方面做得并不好,而且这种不成熟,无法避免;
维护React Native的分支:由于rn的不成熟,需要我们去fork自己并维护rn的代码,但是这对于升级RN版本来说是非常恐怖的;
js的可用性:由于js是一门弱类型语言,这导致在其他工程师在学习和使用的时候很不便利,虽然我们尝试使用了flow和ts,但是效果并不理想(我们将会继续在web中使用ts);
重构:js的弱类型特性导致了再项目重构时非常困难;
JSC(javascriptCore)的不一致性:ios会使用统一的jsc,这并没有什么问题,但是在android上,由于各厂商使用的jsc都不一样,你很有可能会使用默认的jsc(版本非常古老),
而且,在调试的时候我们通常都会使用chrome开发者工具,虽然这在99%的情况下都是没问题的,由于在调试时js是跑在chrome的v8引擎中的,这导致了android调试时,其实运行的环境与我们所期望的并不相同,这很大程度上增加了调试的难度;(笔者也曾碰到过Date对象的实现不一致的问题);
RN的开源库:因为RN需要对各个平台的熟悉,但是通常的用户仅了解一到两个平台,这也导致了RN的开源库在实际使用时,总会或多或少的碰到一些问题;(笔者也在切换打包工具时碰到了依赖库模块规范不规范的问题);
平行的基础设施和功能:我们积累大量的native基础设施,但是在RN,这一切都需要从零开始,在很长的一段时间内,这其实对于我们的工程师的开发效率是有很大的影响的;
crash监控:因为RN在行业中的特殊性,我们不得不开发很多上报的基础设施(如上传sourcemap)等工具去帮助原本已经成熟的工具(如Bugsnag)来进行crash报告统计;
native bridge:由于js的弱类型特性,导致在与native通信时,原本的整形会被转换为字符串,而这些操作很有可能会引起某个平台的调用失败或者崩溃,但在上层却无法得知;
初始化时间:在RN开始渲染前,你必须先初始化运行时,但这会花费至少几秒的时间,这也使得RN APP的初始化时间很长;
初始化渲染时间:不像native的渲染,RN的渲染需要从主线程->js->yoga layout线程->主线程,才能完成渲染,而这通常又会消耗(P90 280ms in iOS 440ms in Android),
导致我们需要采取一些hack手段来避免出现意料之外(显示白屏)的情况
app包大小:RN在包大小上也有一些没法忽略的影响,在Android上,整个RN的包大小(Java + js + native库 + js runtime)已经接近8mb,再加上x86和arm,就已经12mb了;
64位:由于这个issue,我们至今未能在android上完成;
手势:我们通常都会避免在RN的应用里使用复杂的手势,因为iOS和Android对不同手势是的实现和识别都有差异,且没办法统一;
长列表:虽然RN已经对长列表做了一些优化,比如FlatList,但是仍然有许多因为线程的原因带来的限制无法解决;(比如快速滚动时view没办法同步刷新,Text元素没法预先计算高度等)
升级RN:RN升级过程中,新版的RN有时候会依赖React的beta或者alpha版本,但是大部分的第三方库并不会去支持这些“预发布”的版本,这个升级也带来了很大的麻烦;
无障碍访问:RN无障碍访问的API存在的不少问题,使得我们不得不为了一个很小的改动而需要fork一个独立的RN版本来进行修改;
难以修复的crash:在使用中,我们还碰到了一些无法修复的crash;
跨进程保存实例状态:在android上,由于Android自己的机制它会根据设备的内存状态结束位于后台的进程(比如你的RN应用),当重新唤起的时候,你的app使用状态将得不到保存,这一特性虽然可以用redux的技术来fix,但是他并不能完全结局问题,而且在某些情况,甚至会引起崩溃。
其实Airbnb碰到的问题笔者大部分也碰到了,之前的文章也有提及《rn踩坑实践——从输入框“们”开始》、《RN持续踩坑实践》、《RN心路历程》,这里就不再赘述了。
总的来说,对笔者而言,RN更适合用在那种内嵌H5的且交互不会太复杂,而且并不要求全平台一致的场景,而整个APP都要推RN,其实就笔者的经历而言,并不算是一个很好的选择。
另外,近几个月flutter也进入了大家的视野,而且它所推崇的全平台一致性也是一个很吸引人的特性。不过它是基于Dart的,当然对于native的同学不用再写js的也是件好事情,不过也由于不在依赖js,也就摒弃了RN一直使用的jsc的一整套架构,而取而代之使用了基于google自己实现的渲染层api,来达到一致性的效果。甚至令笔者产生了一种“flutter才是未来”的错觉。
当然一切在没有实践之前都是雾里看花,毕竟生态才是一门技术是否能够持续发展的关键,现在谈这些也许,还有点早。
其实整个前端圈子发展得越来越好,新事物层出不穷,未来,说不定Firefox OS类似的技术方案也会成为主流也说不定。