移动开发中,native开发性能和效果上无疑是最好的。html
可是在众多的状况下,native开发并非最优的选择。当需求常常改动的时候,当预算有限的时候,当deadline很近的时候,native开发的成本也就体现出来了。node
这时候,webview开始大放异彩,快速开发、无需从新发布版本、人员成本低的特色就显现出来了。(这里不指hybrid)。react
当使用WebView后,就会逐渐发现,用户体验变得一塌糊涂,长时间的loading、操做dom形成的性能问题等等等等···linux
react native出现后,开辟的一条新的道路。android
公司如今的产品经历了2个大的版本更新后(纯native和部分WebView),如今要经历第三个重大版本的升级了。但此次版本出现了一些状况。ios
版面所有更新、人员有限、预算有限、开发时间短。这就是面临的问题所在。git
hybrid是一整套的将html转为native的开发方式,但使用此方法将会面临的问题是:所有项目须要推翻重作、没有作过此类开发、没有经验。这对咱们来讲是一个很大的冒险。否决!github
后续讨论后,使用native进行框架方面的搭建,大量使用webview进行过渡,开始逐步接入react native。web
这样的好处就是基础内容仍然在可控范围内,可大量重复使用以前的代码。大量使用webview是为了保证项目能够在规定时间内赶工完成···纯属无奈之举。shell
使用react native是为了后续逐步替代webview而进行的。因为在rn方面没有很足的经验,只能一步一步的来,不敢一次性引入太多。
rn的好处就是在于能够在已有的项目中接入开发,而不像hybrid那样,须要所有替换才可使用。这样就能够保证当rn遇到坑没法解决的时候,能够用较少的代价替换回native,保证项目的可控性。
开发时,仍是使用服务器来装载内容较为方便。这里使用的是ubuntu server 14.04。
这里仍是提一句,rn是如何工做的。
在开发时,咱们的框架是这样的:
当正式发布进入到生产环境时,开发服务器上全部的js文件将会被编译成包的形式,直接嵌入到客户端内。这时,已经再也不须要开发服务器的支持了。(热更新后续继续写)
因为资金有限,因此直接搞的虚拟机,安装的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
当返回相似于下图的内容时,证实服务器已经正常启动了(返回的内容其实不少···)。
建立一个测试用的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):
内容较多,请参考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文件。此时就会正常显示界面了。以下图:
发布时,咱们须要先编译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模式须要在正式发布的时候取消掉。