輕鬆教你React Native 混合開發(iOS篇)

joytoy發表於2021-09-09

在React Native的應用場景中,有時候一個APP只有部分頁面是由React Native實現的,比如:我們常用的攜程App,它的首頁下的很多模組都是由React Native實現的,這種開發模式被稱為混合開發。

混合開發的一些其他應用場景:

在原有專案中加入RN頁面,在RN專案中加入原生頁面

圖片描述

原生頁面中嵌入RN模組

圖片描述

RN頁面中嵌入原生模組

圖片描述

以上這些都屬於React Native混合開發的範疇,那麼如何進行React Native混合開發呢?

在這篇文章中我將向大家介紹React Native混合開發的流程,需要掌握的技術,以及一些經驗技巧,

React Native混合開發的教程我們分為上下兩篇,上篇主要介紹**,下篇主要介紹**。

將React Native整合到現有的iOS應用中需要如下幾個主要步驟:

  • 首先,你需要有一個React Native專案;
  • 為已存在的iOS應用新增React Native所需要的依賴;
  • 建立index.js並新增你的React Native程式碼;
  • 建立一個ViewController來承載React Native,在這個ViewController中建立一個RCTRootView來作為React Native服務的容器;
  • 啟動React Native的Packager服務,執行應用;
  • (可選)根據需要新增更多React Native的元件;
  • 執行、除錯、打包、釋出應用;
  • 升職加薪、迎娶白富美,走向人生巔峰!;

1. 建立一個React Native專案

在做混合開發之前我們首先需要建立一個沒有Android和iOS模組的React Native專案。我們可以透過兩種方式來建立一個這樣的React Native專案:

  • 透過npm安裝react-native的方式新增一個React Native專案;
  • 透過react-native init來初始化一個React Native專案;

透過npm安裝react-native的方式新增一個React Native專案

第一步:建立一個名為RNHybrid的目錄,然後在該目錄下新增一個包含如下資訊的package.json

{
  "name": "RNHybrid",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start"
  }
}

第二步:在為package.json新增react-native

在該目錄下執行:

npm install --save react-native

執行完上述命令之後,你會看到如下警告:

圖片描述

其中,有一條警告npm WARN react-native@0.55.4 requires a peer of react@16.3.1 but none is installed告訴我們需要安裝react@16.3.1

npm install --save react@16.3.1

至此,一個不含Android和iOS模組的React Native專案便建立好了。

提示:npm 會在你的目錄下建立一個node_modulesnode_modules體積很大且是動態生成了,建議將其新增到.gitignore檔案中;

透過react-native init來初始化一個React Native專案

除了上述方式之外,我們也可以透過react-native init命令來初始化一個React Native專案。

react-native init RNHybrid

上述命令會初始化一個完成的名為RNHybridiOS的React Native專案,然後我們將裡面的androidios目錄刪除,替換成已存在Android和iOS專案。

2. 新增React Native所需要的依賴

在上文中我們已經建立了個一個React Native專案,接下來我們來看一下如何將這個React Native專案和我們已經存在的Native專案進行融合。

在進行融合之前我們需要將已經存在的Native專案放到我們建立的RNHybrid下,比如:我有一個名為RNHybridiOS的iOS專案,將其放到RNHybrid目錄下:

RNHybrid
├── RNHybridiOS
├── package.json
├── node_modules
└── .gitignore

第一步:配置CocoaPods依賴

接下來我們需要為已經存在的RNHybridiOS專案新增 React Native依賴,在RNHybridiOS目錄下建立一個Podfile檔案(如果已經新增過可跳過):

pod install

然後,我們在Podfile檔案中新增如下程式碼:

target 'RNHybridiOS' do
  # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
  # use_frameworks!

  # Your 'node_modules' directory is probably in the root of your project,
  # but if not, adjust the `:path` accordingly
  pod 'React', :path => '../node_modules/react-native', :subspecs => [
    'Core',
    'CxxBridge', # Include this for RN >= 0.47
    'DevSupport', # Include this to enable In-App Devmenu if RN >= 0.43
    'RCTText',
    'RCTNetwork',
    'RCTWebSocket', # Needed for debugging
    'RCTAnimation', # Needed for FlatList and animations running on native UI thread
    # Add any other subspecs you want to use in your project
  ]
  # Explicitly include Yoga if you are using RN >= 0.42.0
  pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'

  # Third party deps podspec link
  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'

end

接下來在RNHybridiOS目錄下執行:

pod install

執行成功之後,你會看到如下輸出:

圖片描述

如果:出現 xcrun的錯誤,需要安裝Command Line Tools for Xcode,開啟XCode -> Preferences -> Locations 選擇Command Line Tools:

圖片描述

如果:出現 的錯誤,則需要在目錄下執行pod update即可。

圖片描述

第二步:設定App Transport Security Settings

由於我們的RNHybridiOS應用需要載入本地伺服器上的JS Bundle,而且是http的協議傳輸,所以需要設定App Transport Security Settings,讓其支援http傳輸,否則會出現如下錯誤:

圖片描述

由於App Transport Security Settings網上設定的教程有很多,在這裡就不重複了,需要的同學可以Google一下。

3.建立index.js並新增你的React Native程式碼

透過上述兩步,我們已經為RNHybridiOS專案新增了React Native依賴,接下來我們來開發一些JS程式碼。

在RNHybrid目錄下建立一個index.js檔案並新增如下程式碼:

import { AppRegistry } from 'react-native';
import App from './App';

AppRegistry.registerComponent('App1', () => App);

上述程式碼,AppRegistry.registerComponent('App1', () => App);目的是向React Native註冊一個名為App1的元件,然後我會在給大家介紹如何在iOS中載入並顯示出這個元件。

另外,在上述程式碼中我們引用了一個App.js檔案:

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';

type Props = {};
export default class App extends Component {
  render() {
    return (
      
          this is App
        
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  }
 });

這個App.js檔案代表了我們React Native的一個頁面,在這個頁面中顯示了this is App的文字內容。

以上就是為本次演示所新增的React Native程式碼,你也可以根據需要新增更多的React Native程式碼以及元件出來。

4. 為React Native建立一個ViewController和RCTRootView來作為容器

經過上述3、4步,我們已經為RNHybridiOS專案新增了React Native依賴,並且建立一些React Native程式碼和註冊了一個名為App1的元件,接下來我們來學習下如何在RNHybridiOS專案中使用這個App1元件。

建立RNPageController

首先我們需要建立一個ViewController和RCTRootView來作為React Native的容器。

#import "RNPageController.h"

#import 

#import 

#import 

@interface RNPageController ()

@end

@implementation RNPageController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initRCTRootView];
}
- (void)initRCTRootView{
    NSURL *jsCodeLocation;

    // jsCodeLocation = [NSURL URLWithString:@""]; //手動拼接jsCodeLocation用於開發環境 //jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; //release之後從包中讀取名為main的靜態js bundle

    jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; // 透過RCTBundleURLProvider生成,用於開發環境

    //這個"App1"名字一定要和我們在index.js中註冊的名字保持一致

    RCTRootView *rootView =[[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName: @"App1" initialProperties:nil
                                                    launchOptions: nil];
    self.view=rootView;
}
@end

引數說明

  • initWithBundleURL:用於設定jsCodeLocation,有上述三種設定方式,在開發階段推薦使用RCTBundleURLProvider的形式生成jsCodeLocation,release只會使用靜態js bundle;
  • moduleName:用於指定RN要載入的JS 模組名,也就是上文中所講的在index.js中註冊的模組名;
  • launchOptions:主要在AppDelegate載入JS Bundle時使用,這裡傳nil就行;
  • initialProperties:接受一個NSDictionary型別的引數來作為RN初始化時傳遞給JS的初始化資料,它的具體用法我會在****中再具體的講解;

5. 執行React Native

經過上述的步驟,我們已經完成了對一個現有iOS專案RNHybridiOS新增了RN,並且建立了一個RNPageController來載入我們在JS中註冊的名為App1的RN 元件。

接下來我們來啟動RN伺服器,執行RNHybridiOS專案開啟RNPageController來檢視效果:

npm start

RNHybrid的根目錄執行上述命令,來啟動一個RN本地服務:

圖片描述

然後我們開啟Xcode,點選執行按鈕或者透過快捷鍵Command+R來將RNHybridiOS安裝到模擬器上:

圖片描述

6. 新增更多React Native的元件

我們可以根據需要新增更多的React Native的元件:

import { AppRegistry } from 'react-native';
import App from './App';
import App2 from './App2';

AppRegistry.registerComponent('App1', () => App);
AppRegistry.registerComponent('App2', () => App);

然後,在Native中根據需要載入指定名字的RN元件即可。

7. 除錯、打包、釋出應用

除錯

除錯這種混合的RN應用和除錯一個純RN應用時一樣的,都是Command + D開啟RN 開發者選單Command + R進行reload JS,另外大家也可以透過學習

打包

雖讓,透過上述步驟,我們將RN和我們的RNHybridiOS專案做了融合,但打包RNHybridiOS你會發現裡面並不包含JS部分的程式碼,如果要將JS程式碼打包進iOS ipa包中,可以透過如下命令:

react-native bundle --entry-file index.js --platform ios --dev false --bundle-output release_ios/main.jsbundle --assets-dest release_ios/

記得在執行上述命令之前先建立一個release_ios目錄。

引數說明

  • --platform ios:代表打包匯出的平臺為iOS;
  • --dev false:代表關閉JS的開發者模式;
  • -entry-file index.js:代表js的入口檔案為index.js
  • --bundle-output:後面跟的是打包後將JS bundle包匯出到的位置;
  • --assets-dest:後面跟的是打包後的一些資原始檔匯出到的位置;

上述命令執行完成之後,會在release_ios目錄下生成main.jsbundlemain.jsbundle.meta,以及assets目錄(如果RN中用到了一些圖片資源的話)。

將js bundle包和圖片資源匯入到iOS專案中

這一步我們需要用到XCode,選擇assets資料夾與main.jsbundle檔案將其拖拽到XCode的專案導航皮膚中即可。

圖片描述

然後,修改jsCodeLocation,新增如下程式碼:

...
  NSURL *jsCodeLocation;
 //jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
 +jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

上述程式碼的作用是讓React Native去使用我們剛才匯入的jsbundle,這樣以來我們就擺脫了對本地nodejs伺服器的依賴。

提示:如果在專案中使用了,那麼我們需要就可以直接透過CodePush來讀取本地的jsbundle,方法如下:

...
  NSURL *jsCodeLocation;
#ifdef DEBUG
    jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
    jsCodeLocation = [CodePush bundleURL];
#endif
...

到目前為止呢,我們已經將js bundle包和圖片資源匯入到iOS專案中,接下來我們就可以釋出我們的iOS應用了。

釋出iOS應用

釋出iOS應用我們需要有一個99美元的賬號用於將App上傳到AppStore,或者是299美元的企業級賬號用於將App釋出到自己公司的伺服器或第三方公司的伺服器。

接下來我們就需要進行申請APPID 在Tunes Connect建立應用 打包程式 將應用提交到app store等幾大步驟。

因為中有詳細的說明,在這我就不再重複了。

參考

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4650/viewspace-2815024/,如需轉載,請註明出處,否則將追究法律責任。

相關文章