由于一些原因,笔者最近变更到了RN的团队,回归到了hybrid app的开发的圈子中,固然是有蛮多新鲜感和新机遇的,不过遥想起以前在hybrid中各种view之前跳转的头疼等各种问题,笔者怀着忐忑的心情开始了一段波折的hybrid之旅。其实大概的结果之前的文章也有提及了,不过由于大部分只是以“记笔记”的形式描述的,所以难得想抽个时间,好好的总结一下,自己的心路历程。

  众所周知,传统的webapp由于只能发挥native80%不到的机能,在性能和能力上一直为人所诟病,而传统的native app又需要耗费大量的人力,在这个互联网发展速度“过快”的时代,很少会有公司会持续这样“双份”的投资,所以hybrid app在一开始便以更高的性价比获得了业界的青睐,特别是进入react时代之后,react-native一经问世,便受到了业界大量的关注,然而几年过去,react已经更新到16.x,内部也迎来了极大的重构,fiber的推出,异步组件的提出,生命周期函数的unsafe,react似乎正在朝着越来越强大的方向不断进步,而react-native却依旧在0.5x.x的版本使劲挣扎,这里面却有一些不得不说的苦楚。

  RN升级的辛酸

  因为笔者团队维护了多个rn的app,但是由于一些历史原因,两个app几乎是独立的,投入度高的app rn版本能到0.4x,而另一个则仅有0.35.x,但是RN在升级的过程中,往往是伴随着一些破坏性更新的,很多旧的api在新的rn版本中是得不到支持的,但很多机型的兼容性问题或者说一些新的特性又只有新版本的RN才会提供,这也导致了RN升级的这件事是必须要实施的。也许对前端的同学来说,升级不就是换一下package.json的版本号就好了么?但实际上却相当的复杂:

  1、首先,由于xcode本身开发上的一些设计,不管是第三方库还是官方库,都有通过pod或者通过Library的方式来引入,但是Library中的库中的有关引用的写法,随着版本的迭代大部分都不支持了,而且它那种组织方式本身就不是一种可复用的组织方式。

  而且,在调试中你还需要不停地自己手动的清除xcode的缓存,xcode自带的clean并不会清除它的构建缓存,这将导致,你对组件的变更,可能根本没有生效!

  解决方案:在iOS中,修改Library中有关库的引用方式,将它们全部迁移到通过pod来管理

  2、然后,propTypes和createClass两者虽然早起都集成在react的包中(当然RN的包中也有集成),但是随着版本的迭代,两者都被移出的react的主包中,和react-dom一样,需要开发者手动引用,然而对于一个5w+行的项目,组件量达到300+,要进行这样的变更,是一件非常痛苦的事情。。

  解决方案:只有手动的逐行变更代码,使用alias的一些小花招会令你的代码可读性变差

  3、接着,你会发现,之前一直使用的fb提供的官方组件也没有了。。而且官方明确地表示,他们都被废弃了,需要开发者自己去引用react-native-deprecated-custom-components,比如范用度特别高的Navigator,但是为什么官方会废弃它们呢?笔者的个人观点是:“官方也没有提供一个令他们满意的解决方案”。比如刚刚提到的navigator,因为其自身在android上无可避免的会出现状态丢失的问题(虽然这是android的内存管理机制引起的),但是作为结果是,navigator就一定会导致在android上出现view状态丢失的问题,而且这种问题,不管是单vc还是多vc的环境下都会产生,且没有很好的修复办法(虽然从理论上来讲,推行全app的类redux状态管理器可以解决该问题),于是官方变废弃了该类组件。

  解决方案:针对自己的业务场景,自己实现自己需要的功能,笔者的团队就采用了fork官方组件,再二次实现的方式(当然,最终仍然需要状态管理器来解决根本的android的bug)

  4、然后,当你修好了官方组件的bug,觉得你的模拟器将要跑起来的时候,第三方的组件又开始大量报错了,当然,处理了上述那么多问题的你,这时已经想到了原因:因为react的版本和rn的版本都发生了大量的迭代了,其相关组件也跟着需要破坏性更新也是很正常的。但是现实是并不是所有的第三方组件作者都会持续更新。。所以,如果作者还在维护这个组件,那么你是幸运的,如果作者已经没有维护了,那么,要么你能在社区找到能够替换它的组件,要么你还得fork对应的组件,自己进行改动,并且成为维护人。

  笔者也是如此碰到了一些令人头疼的问题:在笔者团队维护的一个app中,使用了一个历史比较悠久的第三方组件,而笔者的团队由由于一些原因,没有持续使用fb提供的packager或者metrobundler进行打包,而是使用了webpack,这导致了原作者可能并不了解前端的模块规范和打包方式,他写的组件能在metro中跑起来,但是当环境切换到webpack时。。整个组件却不能正常编译了。。

  另外比如很多早起的组件在android中都会重载createJSModules的方法,但是到后续的rn版本中,该方法变成了虚方法,不需要重载直接实现就好了,而这些组件的维护者似乎都没有继续维护了,就需要使用者自己去fork组件来修改java代码。

  解决方案:第三方组件,3分依靠作者对自己组件的责任心,7分依靠整个生态的热度,剩下90分,都得靠自己。

  有关升级笔者碰到的问题大概就是这些了,当然这是除去IDE上使用的一些坑(小问题笔者便按下不表了,上文也只提到了严重影响笔者使用的地方),鉴于上文也提到了有关rn打包的事情,笔者接下来再聊聊rn打包的一些感受。

  RN打包的一些感受

  最开始笔者并不了解问什么fb非要重新造一个packager去进行打包,因为rn归根结底也不过是把写的jsx编译成一个es5的jsbundle,依赖对应平台的jsc来执行,同样是“打包”,为什么不使用webpack呢?也许是由于rn自己的特殊性吧?笔者如是想,但是不管是packager还是后来的metro bundler,做的事情几乎和webpack是一样的,而且他们都是用了babel社区的ast能力,去解析jsx文件,就连最后的注入require和__d的定义也和webpack注入webpack_require一样,为什么呢?也许是fb的工程师们在着手做这件事的时候,webpack的文档和社区并不像今时今日这样的强大吧?于是也导致了metro造了一个和webpack几乎类似的轮子,而且它的文档和它的前人一样差!且由于生态和环境相对闭塞,metro bundler的文档严重滞后了很多个版本。

  话说回来,笔者之所以要更换打包工具,主要原因也是因为要做一些拆包的事情,但是由于metro-bundler自身生态的闭塞,且文档确实少得可怜,而业内对于rn拆包打包还是有一些例如haul这类基于webpack的实现的,于是笔者也借鉴了社区的一些智慧,进行该实现。

  但是往往理想很美好,显示很残酷。虽然webpack的生态已经很成熟了,但是在使用webpack来打包rn的时候,还是不可避免的会碰到一些问题,比如:

  1、编译环境的不同。因为webpack针对的不仅是是给浏览器的,还包括了node端,所以会带有一些编译平台所自由的方法或者类库,比如说console、Math、Date、crypto,但是rn由于是在native环境运行的,而fb一开始考虑的场景就和传统的web应用不完全一样,笔者在进行打包工具切换的时候就遭遇了原本metro能够运行的库但是在webpack的编译环境中会报错。

  解决方案:对于编译环境的不同可以尝试使用webpack的target属性为webworker,这个属性设置的时候会更贴切rn的编译环境

  2、图片处理的不同。rn对图片有个比较贴心的处理,它能够自动通过@2x @3x去自动适应2倍和3倍屏的图片,但是原本的webpack是不支持的。

  解决方案:自己编写一个loader去解析图片

  3、一些全局变量。相信进行rn开发的同学或多或少都会使用debugger,但是debugger会依赖rn挂载在全局的一些变量,比如require和__DEV__,而这些变量在webpack里则需要通过providePlugin或者其他的方式注入。

  另外,笔者的项目由于一些历史原因,像比较流行的严格模式都会引起项目运行报错,还有一些json文件的读写,也是metro的编译比较友好(或者没有传统前端严格,比如json文件里的注释),而webpack的相关loader则不会让一些这些“友好”的写法通过编译。

  总的来说,其实大部分使用RN的同学可能和笔者都会有同样的想法:
    “原本美好的write once,run anywhere,但现实是write once,fix everywhere,而且根本没法fix完。”

  其实rn的问题或者说特性还有很多,像那个依赖setState通信的动画,主线不断推送的事件,还有很多单平台才有的属性,都是rn开发的障碍, 所以就笔者而言:目前的rn更适合一些有native能力的团队在一些并不是很要求app性能的条件下使用的解决方案,在没有经过适当优化的基础上其性能表现并不一定有webapp好。

【react native】有关入坑3个月RN的心路历程的更多相关文章

  1. 关于React Native的那些坑

    好久没写博客了,特地把之前接触React Native时遇到的坑总结一下. 初始化一个React Native项目时,可能会遇到以下这些坑: 1.项目版本号与安卓模拟器中安装的 compileSdkV ...

  2. [Web 前端] React Router v4 入坑指南

    cp from : https://www.jianshu.com/p/6a45e2dfc9d9 万恶的根源 距离React Router v4 正式发布也已经过去三个月了,这周把一个React的架子 ...

  3. react native遇到的坑

    1.模拟器报错no bundle url present https://github.com/facebook/react-native/issues/12754 http://www.cnblog ...

  4. 初识React Native,踩坑之旅....

    开启Genymotion Android模拟器后 1.运行“react-native run-android”报端口冲突....解决方法: 2.运行“react-native run-android” ...

  5. react native 遇到的坑

    1.项目中新加入组件,应执行npm install命令 2.项目执行react-native run-android 报错,应进入android目录,执行gradlew.bat clean命令 3.L ...

  6. 记录VSCode开发React Native的一些坑

    当我们点Debug Android时,会弹出以下错误 Could not debug. Unable to set up communication with VSCode react-native ...

  7. React Native填坑之旅--重新认识RN

    如同黑夜里的一道光一样,就这么知道了F8. F8是每年一次Facebook每年一次的开发者大会.每次大会都会release相应的APP,iOS.Android都有.之前都是用Native开发的,但是2 ...

  8. 【react native】rn踩坑实践——从输入框“们”开始

    因为团队技术栈变更为react native,所以开始写起了rn的代码,虽然rn与react份数同源,但是由于有很多native有关的交互和变动,实际使用还是碰到蛮多问题的,于是便有了这个系列,本来第 ...

  9. 为什么学习React Native三点原因

    React Native不到两岁,兼容Android平台刚刚1年.我学习React Native其实也就不到1年,不算长,也不算短. Paul Graham在文章中写过:大多数人真正注意到你的时候,不 ...

随机推荐

  1. appleid

    https://appleid.apple.com/#!&page=signin

  2. 【Nginx】I/O多路转接之select、poll、epoll

    当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一个描述符上面,另外的描述符虽然有数据但是不能读出来,这样实时性不能满足要求,大概的解决方案有以下几种: 1.使用多进程或 ...

  3. [Node.js] Read a File in Node.js with fs.readFile and fs.readFileSync

    We'll read a csv file in node.js both synchronously, and asynchronously. The file we're reading is a ...

  4. Structual设计--Bridge模式

    1.意图 将抽象部分与它的实现部分分离.使他们都能够独立地变化. 2.别名 Handle/Body 3.动机 当一个抽象对象可能有多个实现时,通经常使用继承来协调它们.抽象类定义对该抽象的接口.而详细 ...

  5. 10.2.0.1.1 grid control的启动和关闭

    一.Stopping Grid Control and All Its Components 1.停止OMS服务 [oracle@ocm2 oms10g]$ cd /u01/app/oracle/Or ...

  6. encodeURIComponent

    <script type="text/javascript"> function show(){ var f="#wer中文测试"; f = enc ...

  7. 【大数据project师之路】Hadoop——MapReduce概述

    一.概述. MapReduce是一种可用于数据处理的编程模型.Hadoop能够执行由各种语言编写的MapReuce程序.MapReduce分为Map部分和Reduce部分. 二.MapReduce的机 ...

  8. CXF Spring 使用

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...

  9. Effective C++学习笔记(Part Four:Item 18-25)

     近期最终把effectvie C++细致的阅读了一边.非常惊叹C++的威力与魅力.近期会把近期的读书心得与读书笔记记于此,必备查找使用,假设总结有什么不 当之处,欢迎批评指正: 如今仅仅列出框架 ...

  10. handsontable整理

    hansontable简介 hansontable是一个在线类似Excel的表格编辑器,支持丰富的展现和交互,有多样的单元格类型供配置. 核心是由原生JavaScript构建,充分模块化,支持自定义b ...