【轉(zhuǎn)載】iOS通過Pod快速集成ReactNative環(huán)境

因?yàn)槲覀冺?xiàng)目近期接入RN拥褂,目前接入的版本是 ReactNaitve 0.63版本紊册,在接入過程中放前,發(fā)現(xiàn)RN的項(xiàng)目結(jié)構(gòu)是 RN工程包含 iOS 和 Android工程的目錄干奢。

但是我們對(duì)RN的引入為模塊化引入痊焊,而非全項(xiàng)目。這樣的目錄結(jié)構(gòu)可能對(duì)git管理或者現(xiàn)用工程目錄管理都是一個(gè)問題忿峻。由此考慮能不能直接在iOS的現(xiàn)有項(xiàng)目目錄下直接集成RN薄啥。

看了一下網(wǎng)上上很多人的方式是直接將現(xiàn)用項(xiàng)目 Copy 一份到 RN工程下的 iOS目錄,如果項(xiàng)目人員多的話逛尚,不一定每個(gè)人能很好的操作垄惧,所以產(chǎn)生一個(gè)想法: 在iOS現(xiàn)有工程執(zhí)行 pod install的時(shí)候,自動(dòng)快速集成ReactNative環(huán)境绰寞。

關(guān)于RN的環(huán)境安裝

這里不做太多陳述到逊,官網(wǎng)說的一的非常詳細(xì):中文安裝文檔

總結(jié)就是需要安裝 node 環(huán)境滤钱,和一些輔助插件工具觉壶。

目錄結(jié)構(gòu)分析

首先我們創(chuàng)建空的RN項(xiàng)目查看RN項(xiàng)目的默認(rèn)目錄和引用設(shè)置。

react-native init <項(xiàng)目名稱>

如:react-native init RNTest件缸,這個(gè)過程會(huì)等待一段時(shí)間铜靶,執(zhí)行成功后我們查看目錄:

RNTest
├── App.js
├── __tests__
├── android
├── app.json
├── babel.config.js
├── index.js
├── iOS
├── metro.config.js
├── node_modules
├── package.json
└── yarn.lock
復(fù)制代碼

可以發(fā)現(xiàn) node所有的依賴配置為 package.json文件控制,依賴全部下載在 node_modules目錄下他炊,我們打開默認(rèn)自帶的iOS工程争剿,查看Podfile文件的RN pod依賴配置:

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

platform :ios, '10.0'

target 'RNTest' do
  config = use_native_modules!

  use_react_native!(:path => config["reactNativePath"])

  target 'RNTestTests' do
    inherit! :complete
    # Pods for testing
  end

  # Enables Flipper.
  #
  # Note that if you have use_frameworks! enabled, Flipper will not work and
  # you should disable these next few lines.
  use_flipper!
  post_install do |installer|
    flipper_post_install(installer)
  end
end

target 'RNTest-tvOS' do
  # Pods for RNTest-tvOS

  target 'RNTest-tvOSTests' do
    inherit! :search_paths
    # Pods for testing
  end
end
復(fù)制代碼

首先可以看到, ReactNative 0.63版本支持的iOS最低系統(tǒng)版本為 iOS 10.0痊末。

依賴了兩個(gè)文件:

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
復(fù)制代碼

其他通過 pod path的方式依賴的本地資源:

config = use_native_modules!
use_react_native!(:path => config["reactNativePath"]) 
復(fù)制代碼

我們查看一些 node_modules/react-native/scripts/react_native_pods的這個(gè)文蚕苇,如下:

# 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.

def use_react_native! (options={})
  # The prefix to the react-native
  prefix = options[:path] ||= "../node_modules/react-native"

  # Include Fabric dependencies
  fabric_enabled = options[:fabric_enabled] ||= false

  # Include DevSupport dependency
  production = options[:production] ||= false

  # The Pods which should be included in all projects
  pod 'FBLazyVector', :path => "#{prefix}/Libraries/FBLazyVector"
  pod 'FBReactNativeSpec', :path => "#{prefix}/Libraries/FBReactNativeSpec"
  pod 'RCTRequired', :path => "#{prefix}/Libraries/RCTRequired"
  pod 'RCTTypeSafety', :path => "#{prefix}/Libraries/TypeSafety"
  pod 'React', :path => "#{prefix}/"
  pod 'React-Core', :path => "#{prefix}/"
  pod 'React-CoreModules', :path => "#{prefix}/React/CoreModules"
  pod 'React-RCTActionSheet', :path => "#{prefix}/Libraries/ActionSheetIOS"
  pod 'React-RCTAnimation', :path => "#{prefix}/Libraries/NativeAnimation"
  pod 'React-RCTBlob', :path => "#{prefix}/Libraries/Blob"
  pod 'React-RCTImage', :path => "#{prefix}/Libraries/Image"
  pod 'React-RCTLinking', :path => "#{prefix}/Libraries/LinkingIOS"
  pod 'React-RCTNetwork', :path => "#{prefix}/Libraries/Network"
  pod 'React-RCTSettings', :path => "#{prefix}/Libraries/Settings"
  pod 'React-RCTText', :path => "#{prefix}/Libraries/Text"
  pod 'React-RCTVibration', :path => "#{prefix}/Libraries/Vibration"
  pod 'React-Core/RCTWebSocket', :path => "#{prefix}/"

  unless production
    pod 'React-Core/DevSupport', :path => "#{prefix}/"
  end

  pod 'React-cxxreact', :path => "#{prefix}/ReactCommon/cxxreact"
  pod 'React-jsi', :path => "#{prefix}/ReactCommon/jsi"
  pod 'React-jsiexecutor', :path => "#{prefix}/ReactCommon/jsiexecutor"
  pod 'React-jsinspector', :path => "#{prefix}/ReactCommon/jsinspector"
  pod 'React-callinvoker', :path => "#{prefix}/ReactCommon/callinvoker"
  pod 'ReactCommon/turbomodule/core', :path => "#{prefix}/ReactCommon"
  pod 'Yoga', :path => "#{prefix}/ReactCommon/yoga", :modular_headers => true

  pod 'DoubleConversion', :podspec => "#{prefix}/third-party-podspecs/DoubleConversion.podspec"
  pod 'glog', :podspec => "#{prefix}/third-party-podspecs/glog.podspec"
  pod 'Folly', :podspec => "#{prefix}/third-party-podspecs/Folly.podspec"

  if fabric_enabled
    pod 'React-Fabric', :path => "#{prefix}/ReactCommon"
    pod 'React-graphics', :path => "#{prefix}/ReactCommon/fabric/graphics"
    pod 'React-jsi/Fabric', :path => "#{prefix}/ReactCommon/jsi"
    pod 'React-RCTFabric', :path => "#{prefix}/React"
    pod 'Folly/Fabric', :podspec => "#{prefix}/third-party-podspecs/Folly.podspec"
  end
end

def use_flipper!(versions = {}, configurations: ['Debug'])
  versions['Flipper'] ||= '~> 0.54.0'
  versions['Flipper-DoubleConversion'] ||= '1.1.7'
  versions['Flipper-Folly'] ||= '~> 2.2'
  versions['Flipper-Glog'] ||= '0.3.6'
  versions['Flipper-PeerTalk'] ||= '~> 0.0.4'
  versions['Flipper-RSocket'] ||= '~> 1.1'
  pod 'FlipperKit', versions['Flipper'], :configurations => configurations
  pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configurations => configurations
  pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configurations => configurations
  pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configurations => configurations
  pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configurations => configurations
  # List all transitive dependencies for FlipperKit pods
  # to avoid them being linked in Release builds
  pod 'Flipper', versions['Flipper'], :configurations => configurations
  pod 'Flipper-DoubleConversion', versions['Flipper-DoubleConversion'], :configurations => configurations
  pod 'Flipper-Folly', versions['Flipper-Folly'], :configurations => configurations
  pod 'Flipper-Glog', versions['Flipper-Glog'], :configurations => configurations
  pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configurations => configurations
  pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configurations => configurations
  pod 'FlipperKit/Core', versions['Flipper'], :configurations => configurations
  pod 'FlipperKit/CppBridge', versions['Flipper'], :configurations => configurations
  pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configurations => configurations
  pod 'FlipperKit/FBDefines', versions['Flipper'], :configurations => configurations
  pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configurations => configurations
  pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configurations => configurations
  pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configurations => configurations
  pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configurations => configurations
end

# Post Install processing for Flipper
def flipper_post_install(installer)
  installer.pods_project.targets.each do |target|
    if target.name == 'YogaKit'
      target.build_configurations.each do |config|
        config.build_settings['SWIFT_VERSION'] = '4.1'
      end
    end
  end
end

復(fù)制代碼

第二行代碼就是路徑設(shè)置:

# The prefix to the react-native
prefix = options[:path] ||= "../node_modules/react-native"
復(fù)制代碼

綜上述可以發(fā)現(xiàn),ReactNative的所有本地的path依賴都是 prefix的設(shè)置凿叠,所以我們只要控制好這個(gè)文件的目錄的設(shè)置即可捆蜀,但是我們?nèi)斯ば薷囊膊惶线m,所以可以考慮腳本自動(dòng)實(shí)現(xiàn)修改幔嫂。

集成到現(xiàn)有iOS工程下

如果我們想實(shí)現(xiàn)在現(xiàn)有iOS工程下辆它,集成RN環(huán)境,不保留上一層RN工程目錄履恩,其實(shí)就是把 node_modules 目錄保留到 iOS當(dāng)前項(xiàng)目下一份锰茉,修改對(duì)應(yīng)的路徑配置即可,也就是 所有的 ../node_modules 改為 ./node_modules切心,切不要每個(gè)人手動(dòng)操作飒筑,而是通過腳本自動(dòng)完成片吊。

1.創(chuàng)建一個(gè)iOS Demo.

這里我們創(chuàng)建一個(gè)Demo演示,直接用Xcode創(chuàng)建iOS項(xiàng)目 iOSRNTest协屡。

2.創(chuàng)建 package.json node依賴配置俏脊。

在剛創(chuàng)建的iOS項(xiàng)目目錄下,創(chuàng)建文件 package.json node依賴管理文件:

touch package.json 
復(fù)制代碼

文件配置:

{
  "name": "<項(xiàng)目名>",
  "version": "<項(xiàng)目版本>",
  "private": true,
  "dependencies": {
    "react-native": "0.63.4"
  }
}
復(fù)制代碼

其他的不需要依賴肤晓,在iOS工程中爷贫,只依賴 "react-native": "0.63.4"即可。 注意:這個(gè)文件需要和iOS項(xiàng)目一起提交到git倉庫补憾。

3.編寫 pod 腳本

我們的目標(biāo)是在執(zhí)行 pod install的時(shí)候 ReactNatiive pod工具就是通過ruby語言編寫的漫萄,所以我們可以插入ruby腳本來做一些自動(dòng)化的操作。 在iOS工程目錄下創(chuàng)建ruby腳本文件 Podfile_ReactNative.rb盈匾,開始編寫腳本:

# 定義一個(gè)函數(shù)腾务,在 Podfile文件中調(diào)用此函數(shù)即可
def installReactNativeSdk()

    # 設(shè)置 react_native_pods.rb 文件路徑
    node_mudle_pod_file = "node_modules/react-native/scripts/react_native_pods.rb"

    # 判斷該文件是否存在,如果已經(jīng)存在削饵,表示RN環(huán)境已經(jīng)配置岩瘦,如果沒有存在表示RN環(huán)境還未集成到項(xiàng)目
    if File.exist?(node_mudle_pod_file)
        Pod::UI.puts "\nReactNative 環(huán)境已存在!\n\n"
    else
        Pod::UI.puts "ReactNative 環(huán)境不存在窿撬,準(zhǔn)備下載···"
        # 判斷是否安裝 node環(huán)境
        if system "node -v > /dev/null"
            # 使用 yarn 或 npm 下載依賴
            if system "yarn install || npm install"
                Pod::UI.puts "ReactNative 環(huán)境安裝成功担钮!\n\n"
            else
                Pod::UI.puts "ReactNative 環(huán)境安裝失敗尤仍!請(qǐng)安裝yarn,在命令行執(zhí)行:npm install -g yarn"
                Kernel.exit(false)
            end
        else
            #如果沒有安裝狭姨,提示自行安裝node環(huán)境
            Pod::UI.puts "環(huán)境下載失斣桌病!請(qǐng)先安裝node環(huán)境饼拍,詳細(xì)見:https://reactnative.cn/docs/environment-setup"
            Kernel.exit(false)
        end
    end
end
復(fù)制代碼

此時(shí)ruby的腳本已將編寫完成赡模,接下來讓我們?nèi)ヅ渲?Podfile文件的設(shè)置。

4.配置 Podfile 環(huán)境

如果項(xiàng)目下還沒有 Podfile文件师抄,可以通過 pod init創(chuàng)建漓柑,如果已經(jīng)存在直接設(shè)置。

這里還是用上面創(chuàng)建的空項(xiàng)目 iOSRNTest演示叨吮,編輯 Podfile:

# Uncomment the next line to define a global platform for your project

# 設(shè)置下載源
source 'https://github.com/CocoaPods/Specs.git'

# 導(dǎo)入我們自定義的腳本
require_relative './Podfile_ReactNative'

# 執(zhí)行我們編寫的RN環(huán)境檢測(cè)代碼
installReactNativeSdk()

# 設(shè)置RN配置 依賴辆布,這里需要注意,不要使用 ../node_modules/,而是直接node_modules/
require_relative 'node_modules/react-native/scripts/react_native_pods'

# 這里需要注意茶鉴,RN 0.63版本必須iOS10.0以上版本才支持
platform :ios, '10.0'

target 'iOSRNTest' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # 設(shè)置RN Path 依賴
  use_react_native!(:path => "node_modules/react-native")
end

復(fù)制代碼

到這里環(huán)境全部配置完成锋玲,我們可以直接執(zhí)行 pod install來嘗試是否可以快速集成RN環(huán)境。 如果不出問題涵叮,控制臺(tái)將會(huì)顯示下載ReactNative環(huán)境日志惭蹂。

?  iOSRNTest git:(main) ? pod install
ReactNative 環(huán)境不存在伞插,準(zhǔn)備下載···
yarn install v1.22.10
warning ../../../package.json: No license field
[1/4] ??  Resolving packages...
復(fù)制代碼

等執(zhí)行結(jié)束后,打開 iOSRNTest.xcworkspace 工程盾碗,可以看到 ReactNative環(huán)境已經(jīng)全部集成進(jìn)去媚污!

5.過濾目錄

這里需要注意的是,node_modules目錄為RN依賴的資源廷雅,沒必要提交到git工程耗美,可以在.gitignore文件中過濾掉。

目前我們項(xiàng)目通過這中方式快速集成RN榜轿,RN的模塊直接在對(duì)應(yīng)的位置通過 RCTRootView展示幽歼,其他開發(fā)者不太需要關(guān)心RN的配置,只要會(huì)執(zhí)行 pod install即可谬盐!

因?yàn)閯傞_始做ReactNative甸私,如果您有更好的建議 歡迎評(píng)論!

項(xiàng)目Demo提交到Github飞傀,可以參考皇型!

注意: git clone后,需要保證本地已經(jīng)安裝node的環(huán)境砸烦! 直接執(zhí)行 pod install 弃鸦!

作者:Garrett Gao
鏈接:https://juejin.cn/post/6931727744728301576
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)幢痘,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處唬格。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市颜说,隨后出現(xiàn)的幾起案子购岗,更是在濱河造成了極大的恐慌,老刑警劉巖门粪,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喊积,死亡現(xiàn)場離奇詭異,居然都是意外死亡玄妈,警方通過查閱死者的電腦和手機(jī)乾吻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拟蜻,“玉大人绎签,你說我怎么就攤上這事≡凸” “怎么了辜御?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長屈张。 經(jīng)常有香客問我擒权,道長袱巨,這世上最難降的妖魔是什么牍蜂? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任吏饿,我火速辦了婚禮磁玉,結(jié)果婚禮上蝠猬,老公的妹妹穿的比我還像新娘颜启。我一直安慰自己远寸,他們只是感情好硫痰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布觉至。 她就那樣靜靜地躺著璧尸,像睡著了一般咒林。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爷光,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天垫竞,我揣著相機(jī)與錄音,去河邊找鬼蛀序。 笑死欢瞪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的徐裸。 我是一名探鬼主播遣鼓,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼重贺!你這毒婦竟也來了骑祟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤气笙,失蹤者是張志新(化名)和其女友劉穎次企,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體健民,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年贫贝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秉犹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡稚晚,死狀恐怖崇堵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情客燕,我是刑警寧澤鸳劳,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站也搓,受9級(jí)特大地震影響赏廓,放射性物質(zhì)發(fā)生泄漏涵紊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一幔摸、第九天 我趴在偏房一處隱蔽的房頂上張望摸柄。 院中可真熱鬧,春花似錦既忆、人聲如沸驱负。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽跃脊。三九已至,卻和暖如春苛吱,著一層夾襖步出監(jiān)牢的瞬間酪术,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工又谋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拼缝,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓彰亥,卻偏偏與公主長得像咧七,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子任斋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容