【CSDN 編者按】本文主要介紹 React-Native 的實際使用經驗,對於想要快速入門的同學是有幫助的。
作者 | 佐玉

整體介紹
首先說, React-Native 用來做什麼?傳統的開發中,按照平臺劃分為 iOS , Android , Windows 和 Mac 。其中,隨著移動設備的使用移動端應用的開發也越來越多。傳統上 iOS 應用使用 Xcode 工具、 Objective-C 和 Swift 語言進行開發, Android 應用使用 Android Studio 工具、 Java 和 kotlin 語言進行開發。隨著開發的普及和應用的成熟度,就有人希望能夠用統一的的技術完成更多平臺的開發,降低開發成本,提升開發效率,在這樣的情況下,2015 年 React-Native 誕生了。
React-Native 這個技術主要解決了多個平臺的開發成本和效率問題,只需要掌握前端技術的同學了解一些的 iOS 和 Android 的知識就可以實現跨平臺的應用開發(為了的方便,我們將用 原生 或者 Native 開發代替 iOS 和 Android 開發進行敘述)。隨著使用的增加和技術的深入,尤其對性能最佳化都需要對原生部分有深刻的了解,有些項目還需要編寫原生程式碼實現,所以, React-Native 的開發並沒有官方說的那麼容易和美好。React-Native 的開發技術上要求比原生更高,需要的技術是 前端技術 + 原生技術。
Flutter 也是一門跨平臺解決方案,但是和 React-Native 不同的是,它是一個全新的技術,包括使用的語言都是全新的 Dart 語言,技術層面採用了三棵樹的模式,底層渲染直接和 C++ 互動,而 React-Native 中間層原來採用 bridge ,現在使用 Fabric 等技術提升效率和性能,總體上來說,都是同範疇的技術,項目選型之初看個人喜歡和團隊配置,技術本身都是大公司支持,不需要擔心資源和維護問題。從兩者的標星量上看,目前 Flutter 以 145K 領先一大截。

開發環境
任何技術的入門都離不開環境的配置,記得當初配置一套後端開發環境都要好多繁瑣的步驟,現在前端的開發環境配置也不太輕鬆,尤其當今處理器架構都出現了跨平臺現象, ARM 架構處理器可以運行桌面系統,模擬器可以是 x86 架構,也可以是 ARM 架構,對於應用來說,可能為了應付這些情況,需要同時包含多套架構的二進位制可執行程序和依賴庫。對於開發者,可能需要模擬多種環境來開發調試發佈程序,來保證使用者的體驗。所以,配置環境的這門技術在我看來也算是技術中的灰色地帶了。
當你作為一個新人,打開 React-Native 官網,想要從 get started 開始,以為一切都很美好,那麼,可能是一個 hello 程序都弄半天才跑起來,原因就是開發環境並不像它們介紹的那麼簡單,實際上這是一個綜合性的技術能力,比如,一個對系統有深入了解的,對軟體開發有很多研究的人,一個對系統沒有什麼了解,基礎的 bash 命令和其他工具都沒有用過多少人來說,配置環境的難易程序是完全不同的了。
React-Native 的開發環境,不僅僅需要安裝官網的介紹([中文官網-環境搭建](https://reactnative.cn/docs/environment-setup)),還需要更多,這裡就進行一一介紹。
以 MacOS 開發環境為例,需要安裝 Nodejs (JavaScript 語言運行的必要環境), watchman (程序調試必要元件,檢查檔案改動狀態)。還需要哪些工具呢,讓我們從創建一個 helloApp 應用開始。
創建應用 helloApp 應用,需要執行命令 npx react-native init helloApp 。裡面用到了 npx 和 React-Native , npx 是 npm run 的縮略,所以,需要安裝 npm ,而 npm 集成在了 nodejs 工具集所以不需要單獨安裝, react-native 是 npm 包,一般會自動安裝不需要管理,安裝 Nodejs 的方式主要有兩種,第一種官網下載安裝,第二種(推薦) brew install node , 因為 brew 是 MacOS 非常常用的工具管理器,很多工具都是通過該工具安裝, brew 安裝的工具維護和管理起來非常方便,而且後續,其它的工具可能沒有官網下載安裝方式。而 brew 安裝也是需要手動的,全新 MacOS 並沒有該工具,而在中國,安裝 brew 還是有些麻煩,如果你使用的是最新蘋果 m1 或者 m2 晶片的設備,那麼可能需要考慮 ARM 架構運行 x86 程序的問題。所以,你看說到這裡,開發環境的配置並沒有想象中的輕鬆。有些是對工具需要了解和熟悉,有些需要對系統工具的熟悉,有些對場景的考慮,如果是新人這些問題在所難免,所以為了更加高效的安裝請像下面這樣的執行。
首先,建議 電腦系統保證最新,或者保證電腦系統軟體元件是同一個時期的產品,儘量減少兼容性問題。
其次,確定是 x86 還是 ARM 架構晶片,如果是 ARM 架構,需要在了解 rosetta 模式 和 arch 命令
安裝工具的工具brew ,如果是中國, [請參考](https://gitee.com/cunkai/HomebrewCN), 如果網路足夠好,可以嘗試官網直接安裝[brew 官網](https://brew.sh)。
如果已經安裝了 brew 檢查版本,如果太過老舊請下載重新安裝,如果在一定範圍內可以考慮更新。
到這裡前提的開發環境準備才算是走上正軌。
下面就是使用 brew 安裝 Nodejs , watchman , cocoapods , 如果是 ARM架構設備還需要更新 ruby 。React-Native 一般進行項目依賴管理使用 yarn 工具, 請使用 npm install -g yarn 安裝。實際開發工具還有 Visual Studio Code 或者 webstorm , 如果是 VSCode 需要安裝對應的外掛。
以上這些是開發前端的開發調試配置。
對於開發 iOS 需要安裝 Xcode 以及對應命令列工具。Xcode 13 大概 15 GB 左右。
對於開發 Android 需要安裝 Android Studio 以及 adb 工具,還需要配置環境變數。裡面自帶的 jdk 如果不滿足需求可以自行安裝, oracle jdk 和 open jdk 的差別不大,一個商業收費一個開源免費。Android Studio 安裝包本身不大 1 GB 左右,但是後續下載的 ndk 很大,一個版本就 4/5 GB 。
最後,由於最新 React-Native 版本已經是 ~0.69.0 ,對應 React 版本 ~18.0.0 , 它們和之前的版本兼容性很大,建議使用穩定長期的 TLS 版本,如果最新版本中遇到問題請參考他們的 issues 。
項目運行建議使用 yarn 工具,實際上,很多人習慣於 npm 進行依賴,但是,從性能還是 React-Native 都建議使用 yarn ,具體 npm 和 yarn 可以自行查閱。


創建項目
可能有人會覺得,這個就沒有必要介紹了吧,這樣想的人可以問自己幾個問題:
如何創建支持 TypeScript ?
如何指定在創建時指定 React-Native 的版本?
如何創建 module 項目給別人用?
如何創建支持 Windows 或者 MacOS 平臺的應用?
集成 React-Native 到現有原生應用?
以上這些問題不難就是有些零碎,需要去查找,如果恰好有你關注的問題那就看完這個章節吧,如果沒有則跳過。
創建支持 TypeScript 的項目:
npx react-native init AwesomeTSProject –template react-native-template-typescript
創建指定版本的項目:
npx react-native init AwesomeProject –version X.XX.X
創建 module 的項目個其他應用使用:
npx create-react-native-library@latest react-native-awesome-library
創建 windows 項目:
npx react-native init –template react-native@^0.70.0 cd projectName npx react-native-windows-init –overwrite
集成到現有原生項目:[參考這裡](https://reactnative.cn/docs/integration-with-existing-apps)
iOS 部分
需要使用 pod install 生成 .xcworkspace 檔案,Xcode 打開這個檔案進行原生部分的編譯、調試和運行。
Android 部分
需要使用 Android studio 打開 Android 檔案夾進行原生部分的編譯、調試和運行。

原生部分介紹
React-Native 這個技術框架,不僅僅有前端開發和實現,原生部分也是必不可少的,只是有時候不需要手動實現被忽略了而已,舉個典型應用場景,我們需要寫一個外掛給 React-Native 應用使用,而外掛本身依賴其他原生外掛。這時候,我們需要編寫原生程式碼來 橋接 原生外掛。
前端部分可以使用 vscode 開發和調試,原生部分的開發和調試需要使用 Xcode 和 Android Studio 。
實際上,在 React-Native 運行之前, Web 部分使用 metro 工具將 javascript 程式碼打包成成 bundle 檔案,在原生運行開始的時候,載入並讀取檔案,在調試模式下,還需要啟動 javascript 引擎運行 javascript 程序,這個程序就是 通過 yarn start 運行的調試服務,在 release 模式下,不需要運行該服務。
例如: iOS 的載入資源檔案原始碼:
– (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@”index” fallbackResource:nil]; #else return [[NSBundle mainBundle] URLForResource:@”main” withExtension:@”jsbundle”]; #endif }
開發原生需要注意的以下幾個方面內容。這是讓程序正常運轉的關鍵點。
Web 部分
對於 Web 部分需要調用和接收原生的資料,主要的對象包括:
NativeModules 是原生的控制代碼,想要調用原生的對象和方法需要用到。例如,原生提供方法 callMethod , 則使用 NativeModules.callMethod 調用。
NativeEventEmitter 是原生的事件訂閱對象,想要接收原生的訊息和資料需要用到。
例如:
// NativeModuleApi 原生對象名import{ NativeEventEmitter, NativeModules }from”react-native”;const NativeModuleApi = NativeModules.NativeModuleApi ? NativeModules.NativeModuleApi :throw’Get native module is error’;const eventEmitter =newNativeEventEmitter(NativeModuleApi);
iOS 部分
對於 iOS 部分需要接收和發送資料給 web,主要的對象包括:
接收來自 web 的調用,需要滿足:
需要實現模組,調用 RCT_EXPORT_MODULE(NativeModuleApi)
需要實現具體方法,實現
RCT_EXPORT_METHOD(callMethod
: (NSString *)methodName
: (NSDictionary *)params
: (RCTPromiseResolveBlock)resolve
: (RCTPromiseRejectBlock)reject) {}
需要實現執行的事件,不然無法正常接收訊息
- (NSArray *)supportedEvents {}
發送資料給 web,需要滿足:
實現事件發送類
#import
#import
#import
@interface NativeModuleApi : RCTEventEmitter
@end
調用 RCTEventEmitter 的方法 – (void)sendEventWithName:(NSString *)eventName body:(id)body 發送資料。
Android 部分
對於 Android 部分需要接收和發送資料給 web,主要的對象包括:
接收來自 web 的調用,需要滿足:
實現 ReactContextBaseJavaModule 訊息接收類
@ReactModule(name = NativeModuleApi.NAME)
public class NativeModuleApi extends ReactContextBaseJavaModule implements ExtSdkApi {
public static final String NAME = "NativeModuleApi";
public void initialize() {}
public void invalidate() {}
public void callMethod(String methodType, ReadableMap params, Promise promise) {}
}
發送資料給 web,需要滿足:
保存資料發送對象
private DeviceEventManagerModule.RCTDeviceEventEmitter eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
使用 RCTDeviceEventEmitter 發送資料
eventEmitter.emit(eventName, data);

開發調試部分
在開發和調試模式下,需要額外運行服務來保證 JavaScript 和原生的混合使用。具體運行伺服器命令 react-native start,如果需要運行多臺設備而不相互干擾,可以添加參數 –port ${1024 – 65536}。對於 Android 設備還需要設置資料轉發,都 2022 年了,99%以上的 Android 手機都是 5.0 版本以上,所以,需要設置一下資料轉發 adb reverse tcp:8081 tcp:8081,同樣可以設置不同埠轉發資料,典型應用同時調試多臺設備。對於 HarmonyOS 系統,2.0 以及之前的版本可以和 Android 系統兼容,最新 3.0 系統並不兼容,具體可以看最新的參考資料。
調試 UI 部分
可以使用工具 react-devtools,通過命令npm install -g react-devtools 安裝。
調試如圖:

調試原始碼部分
可以使用 VSCode 直接調試,或者使用 瀏覽器調試。
使用 VSCode 調試,需要安裝必要外掛:React Native Tools。對於格式化可以安裝 prettier 外掛。
以 iOS 為例,可以通過命令 react-native run-ios 從終端啟動,也可以通過打開 iOS 檔案夾下的工作空間檔案使用 xcode工具啟動,啟動之後,通過 vscode 附加進程實現,如果是使用瀏覽器調試,可以在終端輸入 d 或 搖晃手機,彈出 debug 調試界面選擇瀏覽器調試。
通過 VSCode 調試有點麻煩,需要先進行配置 launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to packager",
"request": "attach",
"type": "reactnative",
"cwd": "${workspaceFolder}/example"
}
]
}
VSCode 附加進行配置如圖:

VSCode 調試過程如圖:

真機或者模擬器調試模式如圖:

瀏覽器調試如圖:

啟動服務如圖:

注意:執行調試的時候的根目錄很重要,如果不在根目錄可能需要手動設置,比較麻煩。

測試和驗證
創建項目的時候會提供 __tests__ 檔案夾,裡面的檔案可以編寫測試程式碼。示例程式碼如下:
test("given empty GroceryShoppingList, user can add an item to it", () => {
const { getByPlaceholder, getByText, getAllByText } = render(
);
fireEvent.changeText(getByPlaceholder("Enter grocery item"), "banana");
fireEvent.press(getByText("Add the item to list"));
const bananaElements = getAllByText("banana");
expect(bananaElements).toHaveLength(1); // expect 'banana' to be on the list
});
注意:關於帶有原生程式碼進行單元測試,目前還有問題,啟動提示沒有載入動態庫,這個知道的同學可以留言給我。

最後
任何炫酷的技術背後,都是紮實的基礎,希望同學們在這篇實用指南中或多或少的有所收穫。
後續有時間再講述界面渲染、推送相關、打電話相關,性能最佳化等實用技巧。也歡迎各位點評指正。
作者介紹:
佐玉,85後,環信研發工程師,從事即時通訊行業十年以上,負責過多個中大型項目Windows、Mac、iOS、Android等平臺的客戶端研發,技術從底層協議、業務邏輯到界面設計都全程參與。目前主要從事跨平臺的技術研發工作,對React-Native、Flutter技術都有廣泛的理解和實踐。