React Native 在现有项目中的探路
移动开发中,native开发性能和效果上无疑是最好的。
但是在众多的情况下,native开发并不是最优的选择。当需求经常改动的时候,当预算有限的时候,当deadline很近的时候,native开发的成本也就体现出来了。
这时候,webview开始大放异彩,快速开发、无需重新发布版本、人员成本低的特点就显现出来了。(这里不指hybrid)。
当使用WebView后,就会逐渐发现,用户体验变得一塌糊涂,长时间的loading、操作dom造成的性能问题等等等等···
react native出现后,开辟的一条新的道路。
#0 分析一下下
公司现在的产品经历了2个大的版本更新后(纯native和部分WebView),现在要经历第三个重大版本的升级了。但这次版本出现了一些情况。
版面全部更新、人员有限、预算有限、开发时间短。这就是面临的问题所在。
hybrid是一整套的将html转为native的开发方式,但使用此方法将会面临的问题是:全部项目需要推翻重做、没有做过此类开发、没有经验。这对我们来说是一个很大的冒险。否决!
后续讨论后,使用native进行框架方面的搭建,大量使用webview进行过渡,开始逐步接入react native。
这样的好处就是基础内容仍然在可控范围内,可大量重复使用之前的代码。大量使用webview是为了保证项目可以在规定时间内赶工完成···纯属无奈之举。
使用react native是为了后续逐步替代webview而进行的。由于在rn方面没有很足的经验,只能一步一步的来,不敢一次性引入太多。
rn的好处就是在于可以在已有的项目中接入开发,而不像hybrid那样,需要全部替换才可以使用。这样就可以保证当rn遇到坑无法解决的时候,可以用较少的代价替换回native,保证项目的可控性。
#1 react native开发服务器
开发时,还是使用服务器来装载内容较为方便。这里使用的是ubuntu server 14.04。
这里还是提一句,rn是如何工作的。
在开发时,我们的框架是这样的:

当正式发布进入到生产环境时,开发服务器上所有的js文件将会被编译成包的形式,直接嵌入到客户端内。这时,已经不再需要开发服务器的支持了。(热更新后续继续写)
#2 详细的搭建步奏
#2.0 服务器搭建
由于资金有限,所以直接搞的虚拟机,安装的ubuntu server,基础设置:安装的node版本是v5.8.0。

这里就不详细的讲解node如何安装了···大家自行查找···网上很多···
首先安装Watchman和Flow
git clone https://github.com/facebook/watchman.git
cd watchman
git checkout v4.1.0 # the latest stable release
./autogen.sh
./configure
make
sudo make install
sudo npm install -g flow-bin
具体方法详见:https://facebook.github.io/react-native/docs/getting-started-linux.html#getting-started-on-linux (后面的安装android不需要)
然后创建一个存放代码的目录,比如我的目录是:/var/react/tykReact
切换到此目录下,执行下面语句进行初始化设置。
npm init
如果此语句在设置时不太会用,可在目录下创建package.json文件,文件中的内容如下:
{
"name": "tykReact",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node_modules/react-native/packager/packager.sh"
},
"author": "LunaGao",
"license": "MIT",
"dependencies": {
"react-native":"^0.20.0"
}
}
注意:
1. dependencies下的"react-native":"^0.20.0"是必须的,直接npm install react-native安装在后续会出现问题。
2. scripts下的"start": "node_modules/react-native/packager/packager.sh"是为了启动使用的。(也可以不用)
此时,就可以执行以下语句进行下载react了。
npm install
这个时间比较长,需要耐心等待(我下载了1个小时...)。当然,最好加上sudo,以免出现没有权限等问题。
当安装好后,创建两个文件:index.ios.js和index.android.js。这是用来测试使用的。
index.ios.js
'use strict';
import React, {
Text,
View
} from 'react-native';
var styles = React.StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'red'
}
});
class SimpleApp extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>This is a simple application.</Text>
</View>
)
}
}
React.AppRegistry.registerComponent('TestView', () => SimpleApp);
index.android.js
'use strict';
import React, {
Text,
View
} from 'react-native';
class MyAwesomeApp extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.hello}>Hello, World</Text>
</View>
)
}
}
var styles = React.StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
React.AppRegistry.registerComponent('TestView', () => MyAwesomeApp);
两个文件的代码并不相同,这是直接从
https://facebook.github.io/react-native/docs/embedded-app-android.html#add-js-to-your-app
和
https://facebook.github.io/react-native/docs/embedded-app-ios.html#create-your-react-native-app
复制而来。
至此,目录下应该是如下的样子:

请忽略116221-这样的文件和11f83243da86022a90031e1ca9d758bc,这些是服务启动后自动生成的。npm-debug.log.4046290474这个是错误的日志文件。
没问题后,我们开始启动服务,执行如下语句:
npm start
正常的情况如下图所示:

此时,打开浏览器,输入地址进行访问(192.168.0.203是我的服务器地址,需要替换成实际的地址,本机运行可直接使用localhost):
http://192.168.0.203:8081/index.ios.bundle?platform=ios
http://192.168.0.203:8081/index.android.bundle?platform=android
当返回类似于下图的内容时,证明服务器已经正常启动了(返回的内容其实很多···)。


#2.1 ios集成
创建一个测试用的ios项目,如:react-test
使用pod进行集成,首先要使用npm安装react-native(使用命令:npm install react-native),这个过程可能有点久,然后修改pod文件内容如下:
#platform :ios,'9.0'
use_frameworks!
target "react-test" do
pod 'React', :path => './node_modules/react-native', :subspecs => [
'Core',
'RCTImage',
'RCTNetwork',
'RCTText',
'RCTWebSocket',
# Add any other subspecs you want to use in your project
]
end
pod如何使用这里就不做过多解释了。
然后,在storyboard中拖入一个view,把view的class改为ReactTestView。然后创建ReactTestView,继承自UIView。
ReactTestView.h
//
// ReactTestView.h
// react-test
//
// Created by Luna Gao on 16/3/3.
// Copyright © 2016年 gao.luna.com. All rights reserved.
// #import <UIKit/UIKit.h>
#import "RCTRootView.h" @interface ReactTestView : UIView @end
ReactTestView.m
//
// ReactTestView.m
// react-test
//
// Created by Luna Gao on 16/3/3.
// Copyright © 2016年 gao.luna.com. All rights reserved.
// #import "ReactTestView.h" @implementation ReactTestView - (void)awakeFromNib {
NSString *urlString = @"http://192.168.0.203:8081/index.ios.bundle?platform=ios";
NSURL *jsCodeLocation = [NSURL URLWithString:urlString];
// NSURL *jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"TestView" initialProperties:nil launchOptions:nil];
[self addSubview:rootView];
rootView.frame = self.bounds;
} @end
然后就可以跑起来了。运行效果如下图(样子可能不一样,我的storyboard中增加了tab bar controller):

#2.2 Android集成
内容较多,请参考https://facebook.github.io/react-native/docs/embedded-app-android.html#prepare-your-app
注:这里时需要做 prepare-your-app 和 add-native-code 这两段中的内容。
将onCreate方法修改为:
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mReactRootView = (ReactRootView) findViewById(R.id.test_js);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager, "TestView", null);
在activity_main.xml文件中增加一个ReactRootView,id命名为:test_js。代码如下:
<com.facebook.react.ReactRootView
android:id="@+id/test_js"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/test_text"/>
请注意:在AndroidManifest.xml文件中增加
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
此时运行代码,界面如下:

在命令行中执行:adb shell input keyevent 82
将弹出如下对话框:

点击Dev Settings,点击 Debug server host & port for device 选项如下图:

输入ip地址和端口号,如:192.168.0.203:8081,点击ok。
返回到应用打开页面,再次使用adb shell input keyevent 82命令,点击Reload JS,重新加载js文件。此时就会正常显示界面了。如下图:

#3 如何发布
发布时,我们需要先编译js文件。
在服务器中切换到刚刚的目录下(如/var/react/tykReact),执行如下两个命令:
sudo react-native bundle --minify --entry-file index.ios.js --bundle-output /tmp/ios.jsbundle --platform ios
sudo react-native bundle --minify --entry-file index.android.js --bundle-output /tmp/android.jsbundle --platform android
会在/tmp目录下出现两个文件:
ios.jsbundle 和 android.jsbundle。
将这两个文件分别放入到ios项目和android asset目录下,如下图:

修改ios代码:
ReactTestView.m
// NSString *urlString = @"http://192.168.0.203:8081/index.ios.bundle?platform=ios";
// NSURL *jsCodeLocation = [NSURL URLWithString:urlString];
NSURL *jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"ios" withExtension:@"jsbundle"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"TestView" initialProperties:nil launchOptions:nil];
[self addSubview:rootView];
rootView.frame = self.bounds;
注意:这里需要将ios.jsbundle文件加入到项目中。
修改android代码:
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mReactRootView = (ReactRootView) findViewById(R.id.test_js);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("android.jsbundle")
.setJSMainModuleName("android")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager, "TestView", null);
至此,项目就可以不在依赖开发服务器而直接使用安装包进行运行了~
另:debug模式需要在正式发布的时候取消掉。
React Native 在现有项目中的探路的更多相关文章
- 现有项目中集成Flutter
本文列举了项目开发使用Flutter会遇到的问题,以及如何使用Flutter module在现有项目中集成Flutter,并对其原理进行了分析. 最近在做的一个商业项目,完全的使用Flutter编写的 ...
- React Native 系列(三) -- 项目结构介绍
前言 本系列是基于React Native版本号0.44.3写的,相信大家看了本系列前面两篇文章之后,对于React Native的代码应该能看懂一点点了吧.本篇文章将带着大家来认识一下React N ...
- Roslyn 入门:使用 Roslyn 静态分析现有项目中的代码
Roslyn 是微软为 C# 设计的一套分析器,它具有很强的扩展性.以至于我们只需要编写很少量的代码便能够分析我们的项目文件. 作为 Roslyn 入门篇文章,你将可以通过本文学习如何开始编写一个 R ...
- react native与现有的应用程序集成
(1)通过cocopods 集成 ,以下内容 参考 http://wiki.jikexueyuan.com/project/react-native/integration-existing.html ...
- React Native for android 项目驱动教程
第一节 搭建开发环境 第二节 显示页面标题 第三节 实现页面布局 # React native是什么? React Native,是颠覆性的移动开发技术.它使用js开发,又是原生应用,不同于Hybri ...
- React Native与原生项目连接与发布
前面的各种环境配置按照官方文档一步一步来,挺详细,宝宝在这里就不多说废话了. 其次,前面的配置,我参照的这个博主的文章React Native 集成到iOS原生项目 下面是宝宝掉过的坑(半径15M): ...
- React Native(十五)——RN中的分享功能
终于,终于,可以总结自己使用RN时的分享功能了-- 为什么呢?且听我慢慢道来吧: 从刚开始接触React Native(2017年9月中旬)就着手于分享功能,直到自己参与公司的rn项目开发中,再到现在 ...
- react native的环境搭建中常见问题
搭建完成android的环境,我们就可以继续我们的react native环境的搭建了. 当然,按照fb的安装流程来完成rn的搭建. http://facebook.github.io/react-n ...
- React Native init初始化项目时报错
之前新建RN项目都不会出现这个问题,今天报错如下,这里记录下吧. 报错截图: This will walk you through creating a new React Native projec ...
随机推荐
- 【Oracle XE系列之一】Windows10_X64环境 安装Oracle XE11gR2 X64数据库
一.安装 1.去Oracle官网下载XE版的安装包[下载路径](Oracle Database Express Edition 11g Release 2 for Windows x64),解压. 2 ...
- sizeof和strlen()区别
sizeof关键字和strlen()标准函数都可以用来测试字符串的长度,但是两者有很大的不同 sizeof只能在本函数内, 使用""和不指定长度的字符数组中才能测出字符串的真实长度 ...
- 国内Hadoop应用现状
Hadoop在国内主要以互联网公司为主,下面主要介绍大规模使用Hadoop或研究Hadoop的公司. 1. 百度 百度在2006年就关注了Hadoop并开始调研和使用,截止2012年,总的集群规模超过 ...
- ixgbe 82599 固定源与目标, UDP, 64字节小包, 1488w pps 单核CPU软中断sirq 100%
ixgbe 82599 固定源与目标, UDP, 64字节小包, 1488w pps 单核CPU软中断sirq 100% 注: 测试使用, 正常应用不要开启 五元组不同, 开启ntupleethtoo ...
- emacs 新手笔记(三) —— 为 emacs 做一点简单的定制
ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287 在 emacs 启动时,会加载 ~/.emacs 文件.在该文件中编辑一些 lisp 代码,是一种最为简单的 ...
- 深入理解C语言
语言只是一种工具,任何语言之间都是相通的,一通则百通,关键是要理解语言背后的思想,理解其思想,任何语言,拿来用就行了.语言没有好坏之分,任何语言既然存在自然有它存在的价值. 在一个到处是OOP的年代, ...
- Hacker communities collection
Copy from E安全 Hack Forums: Hack Forums是目前最为理想的黑客技术学习根据地.该论坛不仅在设计上面向黑客群体,同时也适用于开发人员.博主.游戏开发者.程序员.图形设计 ...
- 关于电磁场中的E.B.D.H的理解
电磁场理论中存在四个基本物理量,电场强度E,磁场强度H,电场通量密度D,磁场通量密度B. E:其中E和H最简单,电场中的电荷受到电场力的作用,单位电荷受的力称为电场强度,这种定义得到E的单位为N/C, ...
- Java开发之abstract 和 interface的区别
Java开发abstract 和 interface的区别 java开发里面经常会用到虚函数和接口,这两者的区别是什么呢? abstract: 子类里面只能继承一个父类 interface: 子类可以 ...
- UVALive 5000 Underwater Snipers --二分
题意:一条河岸线y=k,y>k区域有n个敌人,现在要在y<=k区域布置S个狙击手,狙击手的狙击范围为距离自己半径为D的圆内,问满足能够狙死所有的敌人的情况下,离河岸线最近的那个狙击手的离河 ...