一年前我满怀热情地学习React Native,想用一套代码同时开发iOS和Android应用,觉得这是移动开发的未来。但是用了一年,做了几个项目之后,我最终还是选择了放弃,回到了原生开发。不是说React Native不好,而是它没有我想象的那么美好,在实际使用过程中遇到了太多的坑,付出了太多的代价。
今天就来聊聊我这一年用React Native的经历,从入门到放弃,我都经历了什么,遇到了哪些坑,为什么最终选择了放弃,希望能给正在考虑用React Native的朋友一些参考。
一、入门:被跨平台的美好前景吸引
我是在2016年年初开始接触React Native的,那时候React Native刚开源不久,非常火,到处都在讨论,说它是移动开发的未来,一套代码同时跑iOS和Android,开发效率翻倍,热更新体验好,前端开发者可以快速上手,等等。我那时候正好在做前端开发,也想做移动开发,但是又不想学Objective-C和Java,觉得学习成本太高,React Native正好满足了我的需求,用我熟悉的JavaScript和React就能开发原生应用,太完美了。
于是我就开始学习React Native,按照官方文档搭环境,写Hello World,学基础组件,学导航,学状态管理,学网络请求,学得不亦乐乎。那时候觉得React Native真的太好用了,写起来和React一模一样,只是把div换成View,把p换成Text,把img换成Image,其他的逻辑都是一样的,前端开发者几乎零成本就能上手。而且热更新真的太爽了,改完代码保存一下,手机上立刻就能看到效果,不用像原生开发那样等好几分钟编译,开发体验简直不要太好。
学了大概一个月,我就觉得自己掌握了,开始用React Native做项目。第一个项目是一个简单的资讯类App,功能不复杂,就是列表、详情、搜索、个人中心这些。做的过程中虽然遇到了一些小问题,但是都能解决,最后也顺利上线了,iOS和Android两个平台一套代码,开发时间比原生少了大概三分之一,效果也还不错,用户反馈挺好的。那时候我觉得React Native真的太棒了,跨平台真的是未来,我甚至想以后就专门做React Native开发了。
但是好景不长,随着做的项目越来越复杂,遇到的问题也越来越多,我才慢慢发现,React Native没有我想象的那么美好,跨平台也不是那么容易的,很多坑在简单项目里不会遇到,但是项目一复杂,各种问题就都出来了。
二、踩坑:那些让我头疼的问题
做第二个项目的时候,问题就开始多起来了。第二个项目是一个电商类App,功能比第一个复杂很多,有商品列表、商品详情、购物车、订单、支付、推送、定位、相机、相册等等,涉及到很多原生功能,这时候React Native的问题就暴露出来了。
第一个大坑:原生功能需要写桥接,而且坑很多
React Native虽然提供了很多基础组件和API,但是很多复杂的原生功能还是没有的,比如支付、推送、定位、蓝牙、统计、分享、相机滤镜、视频播放等等,这些功能都需要自己写原生桥接,或者用第三方库。
写原生桥接就需要懂原生开发,iOS要懂Objective-C或Swift,Android要懂Java或Kotlin,这就违背了React Native"前端开发者不用学原生"的初衷了。而且写桥接很容易出问题,比如参数传递不对,类型转换错误,回调不触发,内存泄漏,线程问题等等,调试起来非常麻烦,因为要同时调试JavaScript和原生两边的代码,出了问题不知道是哪边的问题,排查起来很费劲。
用第三方库的话,坑也很多。首先是库的质量参差不齐,有的库写得很好,文档齐全,维护积极,但是有的库写得很烂,bug很多,文档不全,作者也不维护,用了之后出问题都没人管。其次是版本兼容性问题,React Native更新很快,几乎每个月都有新版本,很多第三方库更新跟不上,新版本的React Native出来之后,很多库就不兼容了,导致项目升级不了,或者升级之后各种报错。还有就是库之间的冲突,比如两个库都依赖了同一个原生库的不同版本,就会冲突,编译不通过,解决起来很麻烦。
我在第二个项目里,光是集成支付、推送、分享、统计这些功能,就花了快一个月,各种桥接,各种第三方库的坑,各种兼容性问题,搞得我焦头烂额。如果是原生开发的话,这些功能都有成熟的SDK,集成起来很快,但是用React Native,反而更慢了。
第二个大坑:性能问题,特别是长列表和复杂动画
React Native的性能在简单页面上还可以,但是一旦遇到长列表、复杂动画、大量图片的场景,性能问题就很明显了。
最典型的就是长列表,电商App的商品列表,一页要加载几十个商品,每个商品都有图片、文字、按钮,滚动起来就会很卡,特别是快速滑动的时候,会出现白屏、掉帧、卡顿的情况。虽然React Native提供了FlatList组件,比ScrollView性能好一些,但是如果列表项复杂的话,还是会卡,需要做很多优化,比如设置getItemLayout、removeClippedSubviews、keyExtractor,优化列表项组件,避免不必要的重渲染,用缓存图片组件等等,就算做了这些优化,性能还是不如原生的流畅。
复杂动画也是一个重灾区,React Native的动画虽然有Animated API,但是复杂的动画,特别是多个动画联动,或者和手势结合的动画,性能就会很差,掉帧严重,而且写起来很麻烦,调试也困难。原生开发的话,有成熟的动画框架,性能好,写起来也方便,但是React Native的动画就差很多了。
还有图片加载的问题,React Native自带的Image组件功能很弱,没有缓存,没有占位图,加载大图的时候很容易内存溢出,导致App崩溃。所以一般都要用第三方的图片缓存组件,比如react-native-fast-image,但是这个组件也有它的坑,比如某些情况下图片不显示,加载失败等等。
性能问题是我最头疼的问题,因为用户对性能是很敏感的,卡顿、掉帧、白屏,这些都会严重影响用户体验。为了优化性能,我花了大量的时间和精力,做了各种优化,但是效果还是不如原生,这让我很有挫败感。
第三个大坑:版本更新快,兼容性问题多,升级痛苦
React Native的更新速度真的太快了,几乎每个月都有新版本,有时候一个月还更新好几个版本。更新快本来是好事,说明社区活跃,但是对于实际项目来说,更新太快反而不是好事,因为兼容性问题太多了。
每次升级React Native版本,都是一场噩梦。首先是React Native本身的API变化,有的API被废弃了,有的API改了,有的行为变了,升级之后代码各种报错,要改很多地方。其次是第三方库的兼容性,很多第三方库不支持新版本的React Native,升级之后就报错,要么等库的作者更新,要么自己改库的源码,要么换一个库,都很麻烦。还有就是原生依赖的问题,升级之后可能和Xcode、Android Studio、Gradle、CocoaPods这些工具的版本不兼容,各种编译错误,解决起来非常头疼。
我有一次升级React Native版本,从0.40升到0.45,看起来只是小版本升级,结果花了我整整一周时间,各种编译错误,各种第三方库不兼容,各种API变化,改了无数代码,最后终于跑起来了,但是还有一些莫名其妙的bug,又调试了好几天。那时候我就想,原生开发哪有这么多事,版本稳定得很,哪像React Native这样,每次升级都像渡劫一样。
而且因为升级太痛苦,很多项目就不敢升级了,一直停留在旧版本,但是旧版本有很多已知的bug,也没有新功能,而且第三方库也会慢慢停止对旧版本的支持,到最后就变成了技术债务,想升级也升不了了。
第四个大坑:调试困难,开发体验没有想象的好
虽然React Native有热更新,开发体验比原生好一些,但是调试起来还是很困难的。
首先是JavaScript的调试,虽然可以用Chrome DevTools调试,但是很多时候断点不生效,或者变量看不到,或者调用栈不对,调试起来很不方便。而且React Native的错误提示有时候很不友好,报一个错,但是根本不知道是哪里的问题,堆栈信息全是框架内部的,看不到自己的代码,排查起来很费劲。
其次是原生端的调试,如果问题出在原生桥接或者第三方原生库那里,就需要用Xcode或Android Studio调试原生代码,这就需要懂原生开发,而且要同时调试JavaScript和原生两边,来回切换,很麻烦。
还有就是一些奇怪的bug,比如同样的代码,iOS上没问题,Android上有问题,或者反过来;或者debug模式没问题,release模式有问题;或者某些机型上有问题,其他机型没问题。这些问题排查起来非常痛苦,因为你不知道是JavaScript的问题,还是原生的问题,还是某个机型的兼容性问题,要花很多时间去定位。
我在项目里遇到过一个很奇葩的bug,就是在某一款Android手机上,列表滚动的时候会随机崩溃,但是其他手机都没问题,debug模式也没问题,只有release模式才会崩溃。我排查了整整三天,最后发现是某个第三方库和那款手机的系统版本不兼容,改了库的源码才解决。那时候我就想,如果是原生开发的话,这种问题应该会少很多吧。
第五个大坑:招聘难,团队培养成本高
这个是团队层面的问题,React Native虽然火,但是真正精通的人不多,大部分都是只会写简单页面,遇到复杂的原生功能和性能问题就搞不定了。而且React Native要求开发者既懂前端,又懂原生,这样的人更少,招聘起来很难,薪资也比纯前端或纯原生高。
就算招到了人,培养成本也很高,因为React Native的坑太多了,新人进来要踩很多坑才能上手,而且很多问题没有标准答案,需要靠经验积累。团队里如果没有一个React Native大神,项目很容易做着做着就做不下去了,或者做出来的东西质量很差。
我们团队当时就是这样,我算是团队里最懂React Native的了,但是遇到复杂的问题也经常搞不定,需要花很多时间去研究,去踩坑。招了两个新人,学了好几个月,还是只能写简单页面,复杂的功能还是要我来做,导致我压力很大,项目进度也慢。那时候我就想,如果用原生开发的话,招原生开发者容易多了,成熟的开发者也多,团队培养成本也低。
三、放弃:综合考虑之后,还是回到原生
用了一年,踩了无数的坑,付出了大量的时间和精力之后,我最终还是决定放弃React Native,回到原生开发。做出这个决定我也很纠结,毕竟投入了那么多时间和精力去学习和实践,但是理性地分析之后,我觉得对于我们的项目和团队来说,React Native还是不太合适。
我放弃的原因主要有以下几点:
- 项目复杂度高,React Native的性能和功能满足不了需求:我们做的是电商类App,功能复杂,对性能要求高,长列表、复杂动画、各种原生功能都很多,用React Native做起来很吃力,性能也不如原生,用户体验不好。
- 开发效率并没有比原生高多少:简单项目确实快,但是复杂项目,因为要写桥接,要踩各种坑,要做性能优化,要处理兼容性问题,开发效率反而不如原生,而且维护成本更高。
- 稳定性和可维护性差:版本更新快,兼容性问题多,第三方库质量参差不齐,导致项目很不稳定,经常出莫名其妙的bug,维护起来很费劲,技术债务越来越多。
- 团队成本高:招聘难,培养成本高,团队里没有足够的React Native专家,项目风险大。
- 原生开发也没有想象的那么难:后来我花了一些时间学了原生开发,发现其实也没有那么难,Objective-C和Java也没有那么可怕,而且原生开发的工具链成熟,文档齐全,社区活跃,遇到问题很容易找到解决方案,开发体验其实也挺好的。
当然,我不是说React Native不好,它也有它的优点和适用场景,比如简单的资讯类、工具类App,用React Native开发确实快,而且团队如果有React Native专家的话,也能做得很好。但是对于我们这种复杂的电商类App,以及我们这样的团队来说,React Native确实不太合适,所以我选择了放弃。
放弃React Native之后,我开始学习原生开发,用Swift和Kotlin写App,虽然刚开始学习曲线陡一些,但是上手之后发现,原生开发真的很舒服,性能好,功能强,工具链成熟,文档齐全,遇到问题很容易解决,再也不用踩那些莫名其妙的坑了。而且原生开发的市场需求也大,工作机会多,薪资也不错,我觉得这个选择是对的。
四、写在最后
React Native跨平台从入门到放弃,我经历了什么。
以上就是我这一年用React Native的经历,从满怀热情地入门,到踩了无数的坑,最后综合考虑之后选择放弃。这篇文章不是为了黑React Native,只是想分享一下我自己的真实经历和感受,给正在考虑用React Native的朋友一些参考。
React Native是一个很优秀的框架,它的跨平台理念确实很好,也有很多成功的案例,比如Facebook、Instagram、Airbnb这些大公司都在用。但是它也不是银弹,不是所有项目都适合,它有它的优点,也有它的缺点,有它的适用场景,也有它的局限性。在选择技术栈的时候,一定要根据自己的项目需求、团队情况、业务场景来综合考虑,不要盲目跟风,不要觉得什么火就用什么,适合自己的才是最好的。
对我个人来说,虽然放弃了React Native,但是这一年的学习和实践也不是白费的,我学到了很多东西,比如跨平台开发的思路,前端和移动端的差异,性能优化的方法,等等,这些对我后来的原生开发也有很大的帮助。而且我也不后悔尝试过,只有亲自实践过,才知道适不适合自己,这也是一种成长。
技术的世界就是这样,不断有新的技术出现,有的技术会留下来,有的技术会被淘汰,我们要做的就是保持学习,保持开放的心态,多尝试,多实践,找到最适合自己的技术和方向。
最后用一句话结尾:"没有最好的技术,只有最合适的技术。不要盲目跟风,不要害怕放弃,适合自己的,才是最好的。"
祝大家都能找到适合自己的技术栈,做出优秀的产品,在技术的道路上越走越远!
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录