关于react-native的认知
fakefish opened this issue · 0 comments
什么是react-native
不再阐述 http://facebook.github.io/react-native/
目前主流的移动端开发模式
做手机端目前主流是 native 和 hybrid 两种方案,前者优点是性能好,能做的事情多,缺点是需要做各平台定制代码,升级频率的问题,后者优点是能直接升级,能灰度能 ab,缺点是性能差,能做的事情少。
rn 其实和 react 没啥太大的关系,只是用了 react 的语法,所以语法这一层可以换成vue(weex)或者ng(http://angular.github.io/react-native-renderer/) ,甚至是 Nova.js。
大致的结构、原理及特性
最底层是系统,然后是 Objective-C,OC 通过 JSBridge 把接口给最上层的 JS。这里面还有 JS 把注册完的内容通过 JSCore 引擎解析还给 OC 。注意,这里用了一个词叫注册,之所以性能和 Native 相差无几是因为 JS 是跑在一个专门给 JS 开的线程里,所以一个 RN 应用在运行时一般是开着两个线程,偶尔有个网络请求会再开一个网络的线程,由于移动端所有的代码都是异步的,等待系统调用,事件发生了才会去 JS 线程里看看有没有对应处理的东西,因此 JS 的代码更加是异步的异步。所以这种情况下,有些事情会变得很奇怪,比如我在一个 ScrollView 里监听滚动事件做一个动画啥的,会发生页面滚动了但动画延迟了,不是因为 RN 性能不行,而是这种机制下,滚动是系统的,动画是 JS 的,里面差了至少两个线程,要解决这个问题,就是滚动也是 JS 去做,干脆一起延迟。还有个经典的问题,iOS 里有 TableView,各种自动优化,但 RN 里的 ListView 没有用 TableView 的优化,也是因为这个,这种机制算起来是一把双刃剑。
为什么要使用 rn
开发效率
先举个例子,在 RN 中发个网络请求我们直接用 fetch api,而在 OC 中,我们需要新建一个线程去跑任务,然后再切回主线程
[self.spinner startAnimating];
NSURLRequest *request = [NSURLRequest requestWithURL:self.imageURL];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSURLSessionDownloadTask *task =
[session downloadTaskWithRequest:request
completionHandler:^(NSURL *localfile, NSURLResponse *response, NSError *error) {
if (!error) {
// In the case of URL was changed to download smth different.
if ([request.URL isEqual:self.imageURL]) {
// Create image based on local file path.
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:localfile]];
// Set image to be displayed in the main queue.
dispatch_async(dispatch_get_main_queue(), ^{
self.image = image;
});
// Alternative way to do it in the main queue.
/*
[self performSelectorOnMainThread:@selector(setImage:)
withObject:image
waitUntilDone:NO];
*/
}
}
}];
[task resume];
上面的代码是显示加载动画,然后下载一个远程的图片,开个线程跑,跑完取回图片,再同步主线程。
节约多少代码量。
还有最重要是跨平台性,安卓和 iOS 上的业务代码基本是一样的,这些细微的差异可以通过架构去做掉,所以以前可能每个平台各需要2个工程师,外加一个前端,现在一个平台一个,前端一个就可以搞定而且开发效率有极大的提升,业务的迭代一般也只要改前端的代码。
性能
rn 的性能比 Native 略微差一点,可以忽略不计,相比 hybrid 方案好很多。暂没有数据可以提供。
热更新
虽然 rn 的性能比 hybrid 好很多,但是 hrbrid 有 web 方式的优点,就是可以直接热更新,或者 AB 测试,而 Native 不能直接热更新,还需要有个周期去等,虽然 iOS 上的更新速度还挺快,安卓端肯定没有这么好。
由于前面讲的 rn 的机制,js 不是跑在主线程,因此也无法在后台跑检查更新然后直接更新,虽然有code-push 但它的检查是在启动的时候做的,有更新就直接下载了,或者弹个提示更新,确定之后直接下载,不能做一些更佳细致的处理,不过如果有移动端架构的支持,可以后台跑个监控网络情况再更新。
这种机制下,可以做全量、灰度或者 AB 都可以。
文件大小
具体没有做过调查,由于代码量的大量下降,理论上会比同功能的 Native 小一点,而且可以做增量更新,虽然安卓端有插件机制,在这方面优势不大。听新美大的朋友说之前的 app 是 100+m,部分转 rn 之后是 90+m。
学习成本
去哪儿在这方面的成本是,十几个人花了三个多月才完成平台代码的改造。
官方代码的局限
作为社区开源框架,在功能方面需要有所考量,但是具体应用到业务上需要做定制化,需要移动端同学的努力。
移动端
需要学习一点 react 的知识,不过庆幸的是 react 有 jsx 的语法,对安卓的同学来讲,只不过是另一种 xml 的写法。
站在前端的角度来看,这个方面的学习成本不高。对移动端同学来讲,最大的成本在于需要了解 rn 的机制,以及一些相关的源码,需要对框架进行改造。
前端
对前端来讲,react 本身学习成本不高,而且 react 生态圈大部分是基于 web,对生态圈不需要太多的额外的学习,可能唯一要学透的是 redux。其他,需要对 rn 的机制需要有所了解,其他可以不用完全掌握。