iOS已有工程快速集成RN,并且组件化,包含持续集成方案

2,734 阅读5分钟

我们研究RN要解决俩事情,一是怎么在已有工程里跑起来,都有哪些坑;二是怎么在已有的cocoapods工程中把RN当成一个普通组件来使用

浏览官方文档,helloword走起

官网地址(中文版)  官网地址英文版

  • 首先创建一个空的xcode工程,加个按钮用于吊起RN页面

  • Xcode工程做成cocoapod管理组件,pod init以下,然后update即可

  • 按照官方教程安装环境,配置Podfile依赖(工程跑不起来,各种安装失败)

根据官方教程走不通,但是能够了解整个集成流程,然后就是分析podfile怎么配置才能pod update成功。官方教程除了pod update找不到组件的问题之外,还有就是他的方式有很大问题,加了那么多pod path指向的组件!这个问题不解决,相信很多人就不想使用RN了

解决Podfile 组件依赖问题和pod update失败问题

  • 环境安装有问题,改进如下:(注意不用指定版本号,也没有官网说的那些警告,都默认使用最新即可)


  npm install react-native react 

  brew install react-native-cli bundle

  • podfile不要像官网那样写一堆依赖,我的是这么写的

  require_relative '../node_modules/react-native/scripts/react_native_pods'

  require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
 
  platform :ios, '15.1'
 

  target 'Example' do

    # Comment the next line if you don't want to use dynamic frameworks

    use_frameworks!

    pod "Masonry"  

    config = use_native_modules!

    use_react_native!(

                      :path => config[:reactNativePath],

                      # to enable hermes on iOS, change `false` to `true` and then install pods

                      :hermes_enabled => false

                      )
                       

    post_install do |installer|

      react_native_post_install(installer)

    end

  end

  这里有几点特别重要的需要知晓

  * podfile本身本质上就是ruby文件,cocopod读取的时候是当做rb脚本来处理的,因此可以直接使用ruby的require_relative,这个有点像import,也就是指定一个文件夹路径,ruby会自动读取里面的ruby文件,这样就自动把相关依赖引入了。

*** 很多工程配置的platform还是9.0吧?RN大概率是会失败的,因为RN的cocoapod配置要求的高,导致pod update失败,可以先用15

  * 再就是use_react_native才是关键,他是安装RN组件的关键,没有这句就不会安装组件。post_install 那句不加也没问题,但保险起见我加上了

环境按照我说的安装,podfile配置完成之后,剩下的demo就按照官网的写,首先在命令行里执行npm start ,然后直接打开xcode工程运行即可看到RN成功跑起来了,但是如果你现在用的是真机,估计页面效果没生效,因为还有俩坑,如下:

  • demo里这句代码的localhost换成你的本机ip,手机和电脑使用同一个wifi才行 NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];

  • info.plist里别忘了配置App Transport Security Settings

至此,你的工程一定能跑起来,并且看到RN的页面成功展示了!

  目前为止并不具备落地条件,你要打包工程看效果,还要所有人执行npm start?让所有人把工程放node目录下的ios目录下面?搞笑呢吧哈哈

解决已有的工程放到RN下面的问题

目前为止,你的工程是在RN的根目录下的ios目录下面,这样会很奇怪。有没有办法让iOS项目和平时没有区别,RN作为组件随意可插拔集成呢?有。

解决方案在官网有提过,但是没有翻译,很多人可能会忽略,内容如下


Note that RCTRootView initWithURL starts up a new JSC VM. To save resources and simplify the communication between RN views in different parts of your native app, you can have multiple views powered by React Native that are associated with a single JS runtime. To do that, instead of using [RCTRootView alloc] initWithURL, use RCTBridge initWithBundleURL to create a bridge and then use RCTRootView initWithBridge.

 

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.

这是官方给的提示,很多人介绍RN的时候都不会提及。我们的RN入口和功能都只是一个index.js文件,了解前端的都知道,js是可以被打包成bundle的,而官方的这段提示就是突破口,首先是将js打包成bundle,方法如下:


react-native bundle --entry-file index.js --platform ios --dev false --bundle-output "./index.jsbundle" 

官方给出的方案是执行 /node_modules/react-native/scripts/react-native-xcode.sh 脚本文件,js和资源都会自动打包,我试了下是失败的,原因是他们还要求放xcode工程的的shell下面执行才行,这就会有个问题,工程还是必须放node下面的ios目录下面,为了解决工程不放ios目录下面的问题,我们用上面的bundle命令来打包js文件

如果有资源文件的话,使用下面的脚步


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

将打包出来的index.jsbundle文件直接拖进xcode工程,然后改下调用方式如下:


 NSURL *jsbundle = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"jsbundle"];

  RCTBridge *bridge = [[RCTBridge alloc]initWithBundleURL:jsbundle moduleProvider:nil launchOptions:nil];

  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"RNTest" initialProperties:@{}];

  UIViewController *vc = [[UIViewController alloc] init];

  vc.view = rootView;

  [self presentViewController:vc animated:YES completion:nil];

至此,你不用执行npm start开启服务,直接执行xcode工程即可吊起RN页面,现在的开发和集成RN之前流程是一样的!

持续集成自动化的构思

很多公司打包都有持续集成,如何自动化?要解决的问题有: 1,bundle打包自动化 2,bundle导入到工程自动化

  • bundle打包自动化很简单,RN工程作为一个独立组件,xcode工程就是RN组件的demo测试工程,组件发布成cocoapod库的时候自动执行bundle打包js和资源等,将生成的bundle作为cocoapod资源,有pod统一管理

  • bundle导入到工程自动化,既然RN是一个独立组件,就可以和其他pod库一样依赖到主工程,在用到的地方读取组件中的bundle资源来加载RN

集成RN对包体的影响


包体数据以iphone12上的包体为例(不同机型大小不同), ipa大小 和 解压后的.app文件大小(接近用户下载大小)如下:

工程集成RN前 : 291kb - 1.1M 

工程集成RN后 : 2.2M - 9.5M