React Native實(shí)踐一: 如何優(yōu)雅的在已有項(xiàng)目中接入React Native

背景介紹

React Native(后續(xù)簡稱'RN')是最近一段時(shí)間非?;鸬那岸丝缫苿佣思夹g(shù), 目前在Github上watch 2500+, star36000+. 國外使用這項(xiàng)技術(shù)的包括Facebook公司本身的Facebook和Facebook Groups, 國內(nèi)使用這項(xiàng)技術(shù)的APP包括騰訊系的手機(jī)QQ, QQ空間, QQ音樂, 還有阿里的天貓. 阿里系在此基礎(chǔ)上開源了自己的weex, star也有5k+.
目前已經(jīng)在項(xiàng)目中使用了近半年的RN, 表現(xiàn)還算穩(wěn)定. 趟了不少坑, 吃了很多虧. 將自己走過的路記錄下來, 希望對大家有所幫助.

正題

按照RN官網(wǎng)推薦的方式安裝好node, watchman等環(huán)境后, 可以在react-native init AwesomeProject之后跑通RN的demo. 但是這樣得到的工程是純新的, 然而絕大部分情況下, 我們都是在已有的工程里加入RN, 因此, 需要在已有項(xiàng)目中接入RN.
PS:翻不了墻的同學(xué)可以查看此網(wǎng)站. 配置環(huán)境等因?yàn)閴Φ拇嬖跁硪恍┞闊? 這方面的文章網(wǎng)上很多, 就不贅述.

官方推薦的接入方式

官方推薦使用CocoaPods. 半年前曾經(jīng)試過這種方式, 帶來的問題是無法及時(shí)更新RN版本. 不過此時(shí)官網(wǎng)的RN版本是0.31, 而文檔中pod已經(jīng)可以安裝0.26.0版本. 或許不失為一種優(yōu)雅方法, 值得一試.

我推薦的接入方式

趟過的坑

剛開始在項(xiàng)目中引入RN的時(shí)候, 參考的是vczero的一篇文章. 將node_modules整個(gè)拷到項(xiàng)目目錄下. 但是帶來的問題是無法管理node_modules. node_modules文件夾中有數(shù)萬個(gè)文件, 當(dāng)時(shí)年少不懂事, 一口氣將node_modules文件夾上傳SVN, 卻經(jīng)歷了無數(shù)次失敗. 原因是文件數(shù)太多. 當(dāng)然將這些文件分批上傳是一種方法, 然而感覺十分費(fèi)體力, 且萬一后面要更新RN版本, 難道又要經(jīng)歷一次這種痛苦?
于是不打算將node_modules上傳, 而是變成本地管理(即人手拷貝一份). 在經(jīng)歷了幾天蜜月期后, 我們發(fā)現(xiàn)RN本身的限制(其實(shí)就是bug), 要修改RN源碼. 無法使用版本管理的壞處此時(shí)體現(xiàn)了, 我們需要在線下維護(hù)一份修改的代碼. 中間經(jīng)歷了兩次升級RN版本, 于是一個(gè)一個(gè)對照源碼進(jìn)行修改. 往事不堪回首.

那么到底怎么做?

node_modules中包含兩個(gè)部分代碼, JS代碼和原生代碼(OC和Java). 實(shí)際上, 只有原生代碼需要加入原生項(xiàng)目中編譯, 而JS代碼只用于打包bundle. 這樣意味著, 我們可以將node_modules分成兩個(gè)部分, 原生代碼可以隨原生項(xiàng)目的SVN/Git進(jìn)行版本控制, 而JS部分可以通過npm的package.json進(jìn)行版本控制. 這樣, 原生開發(fā)同學(xué)不需要下載node_modules, 也可以對RN的源碼進(jìn)行修改, 而RN開發(fā)同學(xué)也可以享受版本控制的好處.
下面介紹Mac-iOS下的具體步驟:

步驟1

獲取你所需要的RN版本(node_modules).
如在命令行輸入react-native init AwesomeProject, 得到最新版的RN. 獲取AwesomeProject中的package.json和node_modules. 將二者置于與原生項(xiàng)目文件夾平級的地方. 即與iOS和Android文件夾平級之處, 方便雙平臺使用.

步驟2

拷貝node_modules/react-native文件夾至原生項(xiàng)目中, iOS項(xiàng)目保留Libraries文件夾和React文件夾(安卓項(xiàng)目保留ReactAndroid文件夾). 其余所有刪除.

步驟3

iOS項(xiàng)目, 創(chuàng)建Group,放置RN工程項(xiàng)目:
/node_modules/react-native/React/React.xcodeproj
/node_modules/react-native/Libraries/Text/RCTText.xcodeproj
.
.
.
/node_modules/react-native/Libraries/WebSocket/RCT WebSocket.xcodeproj
你需要用到哪些就加哪些. 全部加上也無妨.

步驟4

Build Rules中添加靜態(tài)庫文件.
如libRCTText.a等. libRCT開頭的都加上.

步驟5

Build Settings添加循環(huán)依賴
在Targets-Build Settings-Header Search Paths中加入$(PROJECT_DIR)/項(xiàng)目名/ReactNative/react-native/React 這里要加入的是react-native/React文件夾的路徑, 我的react-native文件夾位于項(xiàng)目名/ReactNative下,因此是這樣寫.

步驟6

設(shè)置Other Linker Flags
Targets-Build Settings-Other Linker Flags中加入-ObjC

步驟7

刪除原生項(xiàng)目中步驟2拷貝過來的react-native文件夾中所有JS文件. 這步本可以和步驟2合為1步,單獨(dú)列出的原因是: 如果沒有刪除其中的JS文件, 其中的JS代碼@providesModuleprovide了很多Module, 會與你在步驟1中的node_modules中的代碼沖突.

步驟8

刪除啟動node服務(wù)腳本.
打開步驟3中引入的RN工程項(xiàng)目:React.xcodeproj-Targets-Build Phases-Run Script. 刪除啟動node服務(wù)腳本的那個(gè)腳本. 即內(nèi)容是if nc -w 5 -z localhost 8081 ; then if ! curl -s "http://localhost:8081/status" | grep -q "packager-status:running" ; then echo "Port 8081 already in use, packager is either not running or not running correctly" exit 2 fi else open "$SRCROOT/../packager/launchPackager.command" || echo "Can't start packager automatically" fi的腳本

步驟9

隨原生項(xiàng)目上傳react-native文件夾, 此時(shí)react-native文件夾中只有原生代碼, 可以進(jìn)行版本控制;
修改package.json, 修改你需要的內(nèi)容(如修改dependencies, 將某些組件固定在某個(gè)版本), 之后用package.json控制更新node_modules.
package.json也上傳SVN, 大家共用這個(gè)管理node_modules.

步驟10

打開命令行, 進(jìn)入與項(xiàng)目平級的目錄(即node_modules所在目錄), 輸入npm start. 啟動node服務(wù).
打開XCode/Android Studio, 進(jìn)入RN開發(fā).

小細(xì)節(jié)

iOS真機(jī)調(diào)試, 需要將localHost改為本機(jī)的ip, 同時(shí)手機(jī)要與電腦處于同一wifi下.
如果要真機(jī)chrome debug, 要修改RCTWebSocketExecutor.msetup函數(shù)的URLString的localHost.
Android真機(jī)調(diào)試就是adb reverse tcp:8081 tcp:8081.
Android環(huán)境搭建一些坑可以參考我這篇文章.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容