出于公司需求,需要再已經(jīng)運(yùn)行了5年的項(xiàng)目中添加react native .看到網(wǎng)上基本上就是照抄RN中文網(wǎng)的, 時間也很久了, 把自己集成的過程記錄下,嘗試總結(jié)下 ,希望幫助需要的人吧。
1.RN環(huán)境
我們的開發(fā)電腦安裝RN的環(huán)境, 這里就不多做介紹了,RN中文網(wǎng)寫的很詳細(xì)。
2. 安裝 JavaScript 依賴包
在項(xiàng)目根目錄下創(chuàng)建一個名為package.json的空文本文件,填入內(nèi)容,填入什么內(nèi)容呢?
其實(shí)你可以使用react-native init 項(xiàng)目名命令創(chuàng)建一個純RN項(xiàng)目,然后去參考其ios目錄中的package.json 和 Podfile文件【備注:RN的最新版本0.6+開始使用cocopods管理ios項(xiàng)目,并管理ios和RN的項(xiàng)目依賴】
這里簡單貼一下示例:
package.json
{
"name": "myRactNative",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"react": "16.9.0",
"react-native": "0.61.5"
},
"devDependencies": {
"@babel/core": "^7.8.7",
"@babel/runtime": "^7.8.7",
"@react-native-community/eslint-config": "^0.0.7",
"babel-jest": "^25.1.0",
"eslint": "^6.8.0",
"jest": "^25.1.0",
"metro-react-native-babel-preset": "^0.58.0",
"react-test-renderer": "16.9.0"
},
"jest": {
"preset": "react-native"
}
}
然后運(yùn)行yarn add react-native
這樣默認(rèn)會安裝最新版本的 React Native,同時會打印出類似下面的警告信息(你可能需要滾動屏幕才能注意到):
warning "react-native@0.52.2" has unmet peer dependency "react@16.2.0".
這是正?,F(xiàn)象,意味著我們還需要安裝指定版本的 React:
yarn add react@16.2.0
注意必須嚴(yán)格匹配警告信息中所列出的版本,高了或者低了都不可以。
如果你使用多個第三方依賴,可能這些第三方各自要求的 react 版本有所沖突,此時應(yīng)優(yōu)先滿足react-native所需要的react版本。其他第三方能用則用,不能用則只能考慮選擇其他庫。
3. 安裝 Cocopods 依賴包
Podfile
platform :ios, '9.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
target 'myRactNative' do
# Pods for myRactNative
pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
pod 'React', :path => '../node_modules/react-native/'
pod 'React-Core', :path => '../node_modules/react-native/'
pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
target 'myRactNativeTests' do
inherit! :search_paths
# Pods for testing
end
use_native_modules!
end
target 'myRactNative-tvOS' do
# Pods for myRactNative-tvOS
target 'myRactNative-tvOSTests' do
inherit! :search_paths
# Pods for testing
end
end
這里需要注意兩點(diǎn)
【1】Podfile 文件中,node_modules 目錄一般位于根目錄中 但是如果你的結(jié)構(gòu)不同,那你就要根據(jù)實(shí)際路徑修改下面的:path =>
我貼一下我示例項(xiàng)目中的目錄結(jié)構(gòu)

【2】Podfile 文件中,platform :ios, '9.0' 這個要注意 一定最低是9.0 否則pod instal的時候會出現(xiàn)類似Folly glog DoubleConversion 安裝不上,包錯誤?的問題??梢栽囈幌?。
剩下的就是 pod install了,如果這個過程不出錯,恭喜你!!已經(jīng)基本完成了項(xiàng)目集成RN的工作~
其實(shí)說白了 就兩大步, 搞定package.json 和 Podfile
剩下的就是在根目錄中新建一個index.js的RN入口文件,和在OC中調(diào)用進(jìn)入RN場景的代碼了,這里簡單貼一下代碼:
index.js
/**
* @format
*/
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
native view -> 跳轉(zhuǎn)RN
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"myRactNative"
initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
@end
4. 下面我說下 我項(xiàng)目中遇到的坑
【1】Pods/boost-for-react-native/boost/compatibility/cpp_c_headers/cstdlib:11:11: error: no member named 'abort' in the global namespace
解決辦法: Xcode: cstdlib no member named “xxx” in the global namespace
最后的最后, 我興奮的運(yùn)行了起來, 完美 perfect !成功了耶,于是打包測試, WC,跳轉(zhuǎn)到RN界面 居然 閃退了?。。?/h1>
嘚吧了那么多,其實(shí)還有一小點(diǎn)需要我們注意,這個是原項(xiàng)目集成RN中容易忽略的點(diǎn),
先解釋一下吧,
其實(shí)在release 環(huán)境下打包 代碼中有這樣一句
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
那么這個main.jsbundle怎么生成呢,我也網(wǎng)上找了rn代碼打包成bundle的命令 , 什么使用curl命令生成 main.jsbundle 還有什么react-native bundle --entry-file index.ios.js --bundle-output ./bundle/ios/index.ios.jsbundle --platform ios --assets-dest ./bundle/ios --dev false
我都試一試了,反正在我這邊都不行, 打包后一跳轉(zhuǎn)RN界面就會閃退,
其實(shí)在RN中文網(wǎng)集成到現(xiàn)有項(xiàng)目中一段未翻譯的英文標(biāo)注
When moving your app to production, the NSURL can point to a pre-bundled file on disk via something like [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];. You can use the react-native-xcode.sh script in node_modules/react-native/scripts/ to generate that pre-bundled file.
就是這個 react-native-xcode.sh script腳本
這個 react-native-xcode.sh script腳本 添加到 你項(xiàng)目中

就是這個Bundle React Native code and images 內(nèi)容如下:
export NODE_BINARY=node
../node_modules/react-native/scripts/react-native-xcode.sh

注意路徑哦,個別項(xiàng)目可能不同
~ 另外 我的項(xiàng)目 剛集成了 RN 的熱更庫 微軟的 code-push 有時間寫也一下集成歷程...
到此真正的結(jié)束了,你可以愉快的 codeing rn 代碼了...