起因
Facebook官方对react-native(下面简称RN)在iOS端的集成方式为本地Pod库,这种方式有两个缺点:
项目更新RN依赖版本较为繁琐,需要对项目中的node_modules文件夹进行文件操作,这种方式不利于模块化和版本管理
对pod形式的库项目支持不友好,pod库的依赖只能支持name+version的形式,无法支持本地源码形式的依赖
综上,需要在公司私有Pod仓库中添加对RN的支持。
一些尝试
常规方式
常规方式Pod库的常规操作方式为先lint再push,这种方式在RN上会遇到很多错误,解决了一批错误后最终停止在一个x86_64的错误上:Undefined symbols for architecture x86_64
,这是一个比较常见的编译错误,但是尝试了很多方式后仍然无法解决。这里记录下关键问题,供后续参考:
- lint和push的时候需要增加几个关键选项:
1 | --use-libraries #不加会报一些c++库找不到的错误 |
- 如果对本地仓库有依赖,sources要指定本地私有仓库,不然默认是查找Cocoapods官方仓库
曲线方式
另外一个思路是考虑先把RN整体打成framework,再集成到Pod库中。这种方式最终停止在一个错误:invalid bitcode signature
,跟上面的问题一样,没有搞定。
手动操作Spec仓库方式
在没有思路的时候,在google尝试搜索关键词react-native podspec
,发现一篇文章:私有Pods集成react-native库,里面分享通过pod ipc spec
命令将.podspec文件转成.podspec.json格式文件,然后将代码和.podspec.json分别提交到代码仓库和Pod仓库的方式,绕过lint和push的常规步骤。
这里需要注意的是,代码提交到私有源码库和podspec提交到私有Pod库是互相独立的操作。可以只提交Podspec到私有Pod库,但是代码提交到到私有源码库有两个好处1
21. 内部网络更新速度快
2. 可以修改代码后自定义版本
尝试了一下,虽然遇到一些编译错误,但不是整体编译不过,而是一些RN内部类找不到,说明至少RN放到Pod仓库了。沿着这个思路往下探索,最终解决。
其中RN依赖了一些第三方库,包括folly、yoga、glog等,对于RN依赖的第三方库,处理原则是如果在官方Pod仓库没有对应的版本,都需要以私有Pod的方式提供。具体需要处理哪些库,需要根据当前RN版本来判断(例如Folly的2016.10.31.00在官方库没有,但是2016.09.26.00却能支持)。
操作步骤
- 去
https://github.com/facebook/react-native/tags
下载对应版本的RN源码包,解压缩后将源码提交到本地仓库`git@gitlab.jinhui365.cn:mobile/react-native.git` master分支。这里需要注意的问题是要保证该版本所有文件都会提交,包括.开头的文和文件夹。 - 在gitlab上为新版本打一个tag,tag名称约定为v{版本号},例如版本号为0.57.4,则tag名称为v0.57.4。
- 进入源码根目录,执行
pod ipc spec React.podspec >> React.podspec.json
。这里需要注意的是不要污染本地源码仓库,可以在另外一份源码拷贝上操作。 打开React.podspec.json文件,将source字段修改为本地的RN源码仓库地址和对应地址
1
2
3
4"source": {
"git": "git@gitlab.jinhui365.cn:mobile/react-native.git",
"tag": "v0.57.4"
}将修改后的React.podspec.json放到私有Pod仓库对应的目录下提交。例如
React/0.57.4/React.podspec.json
- 在源码根目录下,进入
ReactCommon/yoga
,执行pod ipc spec yoga.podspec >> yoga.podspec.json
打开yoga.podspec.json,将source字段修改为本地的RN源码仓库地址和对应地址,并将source_files字段修改为
"ReactCommon/yoga/**/*.{cpp,h}"
,public_header_files字段修改为:"ReactCommon/yoga/yoga/{Yoga,YGEnums,YGMacros}.h"
将修改后的yoga.podspec.json放到私有Pod仓库对应的目录下提交。例如
yoga/0.57.4.React/yoga.podspec.json
本地址行
pod repo update {仓库名}
至此,可以在项目中通过name+version的形式引用RN的pod依赖。
0.53.3的问题
RN在0.53.3上有一些编译问题,李杨在React-Native混编学习#iOS环境搭建 提到过相关解决方案,已按照该方案经将源码修改后tag为0.53.4。可以通过引用0.53.4来规避这些问题。
私有库依赖私有库
金汇移动端目前负责的业务较多,不同的业务之间会复用工具库(如路由库、日志库等)。同一个业务功能,有可能需要在不同的App之间复用(如民工汇、支付SDK)。因此,依赖的路径为APP->业务库->非业务库。
iOS的依赖管理与Android不同。Android统一使用gradle文件来管理依赖,而iOS主项目使用Podfile管理,库项目使用podspec管理,并且库项目无法依赖本地文件。
因此新建了私有库PodLibTest来测试了下,编译通过。这里记录下常见命令:
1 | pod lib create PodLibTest #创建pod库项目 |
总结
Cocoapods在依赖管理方面不够完善,提升了iOS工程化的难度等级。因此需要iOS工程师对相关领域知识研究地更深入,才能达到与Android同水平的工程化程度。
面对非常见疑难问题,通过简单的关键词搜索可能不太好找到解决方案。需要从两个方面着手,一方面多尝试关键词组合,找到和你遇到同样问题的人写的文章或帖子;一方面深入研究官方文档货项目源码,从原理层着手分析问题。