ReactNative 工程搭建和改造

date
May 21, 2019
slug
ldxxvnlg
status
Published
tags
ReactNative
summary
type
Post
 
官方教程中文教程。网上也有很多其他资料,可自行搜索。
两种教程里都提到 2 种方式:沙盒方式(expo)、与原生混合(Native Code),他们的区别在于是否会编写原生代码。expo 方式中集成了部分原生的功能,直接引用 expo sdk 即可。也可使用yarn ejected根据提示对工程进行转原生混合方式,应该不能逆转吧。
考虑到国内对 APP 的要求,如个性化、性能要求等等,还是选择与原生混合方式较好,方便后期扩展。
下面以iOS为例,记录下我的改造过程:

一、工程构建

1、工程目录构建
$ yarn global add react-native-cli
$ react-native init doctor_app
$ cd doctor_app
$ yarn install  // 此步可能在init时已经自动执行过了
2、iOS 添加 pod 支持
$ cd ios
$ pod init
$ vim Podfile   // 更改platform为9.0,可以移除其他未用的target
$ pod install
双击打开生成的 doctor_app.xcworkspace 后,会在 doctor_app 工程中的 Libraries 看到 React 的默认支持。这时 iOS 工程项目已经初步完成。如果需要添加原生支持的 RN 三方依赖,以react-native-device-info为例
$ yarn add react-native-device-info
$ react-native link react-native-device-info    // 推荐用link自动方式,也有其他多种方式,按照库的问题操作即可
$ cd ios
$ pod install
最后,就可以在 RN 代码里 react-native-device-info 的 API,编译后 APP 能正常运行。

二、[!] React has been deprecated

在上面pod install之后可能会注意到控制台有黄色的提示[!] React has been deprecated,同时发现 pod 过程中安装React 0.11.0,但明明 package.json 里使用的"react-native": "0.59.8"
有强迫症的表示不能接受,哈哈…..如果此时通过 pod 方式安装code-push,编译还会报错React/RCTEventEmitter.h file not found in CodePush.h,此问题在 code-push 的 issues 上有提到很多次。我实际工作中遇到很多类似报 RN 的头文件未找到的问题。是不是很尴尬!明明装了 RN,而且还安装了两个版本。
大致原因就是头文件引用的问题。下面用白话简单阐述,虽说工程构建时添加了RN 版本 A,走的 Library 形式,但是用 pod 安装的 RN 依赖并不能准确找到RN 版本 A的头文件,导致会自动安装一个RN 版本 B(即 0.11.0)。这时用 pod 方式安装的 code-push 会自动首先找到RN 版本 B,报上面的错误也能理解,毕竟 code-push 发布时依赖 RN 版本最低要求 0.xx.x(仅是我猜测,未验证!)。
解决方式就是将 Library 里的 RN 版本 A 移到 Podfile 里。

三、转移 React Native 到 Podfile

即把下面这些 Library 转移到 Podfile 里去,这时有没有想起什么?转移原理其实是集成到现有原生应用,只不过转移后还保留了 react-native-cli 脚手架在 Xcode 中的配置,比如打包 RN 代码的脚本等。一般情况下将 RN 集成到现有原生 APP 里,在打包 APP 时需要首先打包 RN 的离线文件,更详细见React Native iOS 打包详解
notion image
16adebab8ea98007
在 Podfile 里添加下面的代码,然后 pod install 即可会安装两个 RN 版本的问题。
  pod 'React', :path => '../node_modules/react-native', :subspecs => [
    'Core',
    'CxxBridge',
    'DevSupport',
    'RCTText',
    'RCTImage',
    'RCTNetwork',
    'RCTWebSocket',
    'RCTAnimation',
    'RCTLinkingIOS',
    'RCTSettings',
    'RCTGeolocation',
    'RCTActionSheet',
    'RCTVibration',
    'RCTBlob',
  ]

  pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'

  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'
为了保险起见,将上述截图里的 RN 子模块全部移除掉Remove Reference,不是Move to Trash。接着用 Xcode 编译试试 APP 看能不能正常运行。
到此,RN 工程的基本改造完成,尽情使用 Podfile 安装 RN 第三方原生依赖吧。
2019-07-11 18:57:57 更新
最新的 RN 版本 0.60 里关于 iOS 的部分改动,和我此篇文章改造思路几乎一致,可能 Facebook 自己也意识到此问题。详情见 React Native 0.60 新特性
notion image

© 刘德华 2020 - 2023