最新版 React Native iOS 项目搭建纪实,适用 M1/M2 Apple 电脑

5,432 阅读6分钟

要研究一项技术,最怕 “顺利运行起来” 这么起码的事都成为逾越不过去的障碍,相信很多同学根据官方 Setting up the development environment · React Native 文档操作,未能顺利启动项目,对之前纯 Web 前端的工程师来说,应该是很大概率的。

能够顺利运行 RN 项目后,即使没法儿走通完整的工作流闭环,如不会打包、推送到应用商店等等,也能够搞明白其中组件、API、架构一类,那时 “走通工作流闭环” 也成了顺其自然的事儿。

本文囊括了大体的 React Native 工作流闭环:项目环境、创建、启动、调试、打包、安装。

没有相关痛苦经历的同学,请帮忙检阅这篇文章,权当作温故罢了。😜

使用最新版 React Native 搭建 Android 项目参见《在 macOS 里搭建最新版 React Native Android 项目纪实》。

本文如果没能帮你成功搭建、启动 RN Android 项目,无论是 Intel 芯片或者 Apple Silicon(M1 / M2)芯片的电脑,找我!微信:iyoooooooo。或者入群👇🏻一起交流。避免一万个哈姆雷特的问题,正好查漏补缺,继续完善这篇文章。 29A279A8-50BD-4E6E-8AF7-7455A6EDEFF3.png

第一阶段:环境

下述环境是可以成功运行项目的,供参考、检查。RN 项目搭建的关键也在于环境。

macOS

macOS Monterey 12.6.1(Intel)

网络

全局科学上网,最好是千兆网速。

react-native

react-native v0.70.6 @react-native-community/cli v9.3.2

Package Manager

具体安装方式见各自官网。

homebrew 3.6.12-9-g840f49a,是一款自由及开放源代码的软件包管理系统,用以简化 macOS 系统上的软件安装过程。

npm v9.1.2,JavaScript 包管理器。推荐 NPM + PNPM。参阅《pnpm 是凭什么对 npm 和 yarn 降维打击的》。

gem v3.1.6,ruby 世界的软件包叫 gem,也就使用这个名字作为这些包的管理器的名字了。重心在包的构建、安装上。如果要将 ruby 项目构建成 gem,使用它。

bundler v2.1.4,重心在依赖关系上,是一款依赖管理工具,帮助摆脱依赖地狱,并确保需要的 gem 存在于开发、暂存和生产中,并是确切的,为 Ruby 项目提供一致的环境。如果是一般性的 ruby 项目,并不需要构建成 gem,使用 bundler 统一为项目管理依赖。

cocoapods 1.11.3,Swift、Objective-C Cocoa 项目包管理器。Gem、Homebrew 都可以安装它,优选 Gem。

OpenSSL@1

export LDFLAGS=“-L/usr/local/opt/openssl@1.1/lib”
export CPPFLAGS=“-I/usr/local/opt/openssl@1.1/include”
export PATH=“/usr/local/opt/openssl@1.1/bin:$PATH”

这个版本完全是为了安装需要 OpenSSL@1 系列的软件准备的,可以通过 Homebrew 安装 OpenSSL@1 系列最新版本,但需要在 ~/.bashrc 中暴露上述环境变量,如果使用了 ZSH,在 ~/.zshrc 中设置即可。注意,路径中的 “openssl@1.1”,替换为自己系统中实际的名称,可以到 /usr/local/opt 根目录查找。

执行 exec $SHELL 重载命令行会话后,运行 openssl version -d 可获取 openssl 配置文件的位置。想要获取其它信息,运行 openssl version -help 即可,会输出如下提示,

Usage: version [options]
Valid options are:
 -help  Display this summary
 -a     Show all data
 -b     Show build date
 -d     Show configuration directory
 -e     Show engines directory
 -f     Show compiler flags used
 -o     Show some internal datatype options
 -p     Show target build platform
 -r     Show random seeding options
 -v     Show library version

OpenSSL@3

使用 Homebrew 安装(brew install openssl@3)。

这个版本并不需要配置到环境变量中,只是在构建项目时,有些模块会用到,比如, 6BD75A4B-D33F-4CE0-AA84-F5D8917656D8.png

防止有其它场景需要将它配置到环境变量中,所以这里也将配置方式贴出来,注意,使用 Bash 就在 ~/.bashrc 中暴露环境变量,如果使用了 ZSH,在 ~/.zshrc 中设置即可,

openssl@3 is keg-only, which means it was not symlinked into /usr/local,
because macOS provides LibreSSL.

If you need to have openssl@3 first in your PATH, run:
  echo 'export PATH="/usr/local/opt/openssl@3/bin:$PATH"' >> ~/.zshrc

For compilers to find openssl@3 you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl@3/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl@3/include"

版本管理器

具体安装方式见各自官网。

nvm 0.39.1,Node 版本管理器。

rvm 1.29.12 (latest),Ruby 版本管理器。

运行时

node v18.12.1”,使用 NVM 安装,安装后的位置在 $HOME/.nvm/versions/node/v18.12.1/bin/node,可以通过 which node 指令检查,另外软链(ln -s $(which node) /usr/local/bin)到 /usr/local/bin/node 位置,防止构建 iOS 应用时有些包需要使用到这个软链。

ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [x86_64-darwin21]”,使用 RVM 安装。具体安装什么版本,跟着项目里 “.ruby-version” 或者 Gemfile 文件声明的来,目前最新 RN 模板里声明需要 2.7.5 版本的 ruby。

SDK

DriverKit 22.1, iOS 16.1, macOS 13.0, tvOS 16.1, watchOS 9.1

编辑器

Xcode Version 14.1 (14B47b),对 RN 项目构建、打包、修改原生部分等,在 Xcode 中操作。

Visual Studio Code,平常修改 React 相关代码,也是主要的工作位置。

模拟器

启动 Xcode,并不需要打开任意项目,找到 Xcode 菜单栏,顺序 “Xcode -> Preferences” 操作打开 Xcode 偏好设置弹窗,切换到 “Platform” 选项卡,模拟器。 7105E23D-1856-4F11-A459-B8026BD5F8CE.png

最新版本的 Xcode 一般都内建最新的模拟器,如果需要安装其它模拟器,点击右下角的 + 号即可。 Frame 1.png

React Native 应用程序以 iOS 12.4 或更新版本为目标,所以除了内建的最新模拟器,还可以安装下列方便测试,

  • iOS 12.4 Simulator
  • iOS 13.7 Simulator
  • iOS 14.5 Simulator
  • iOS 15.5 Simulator
  • iOS 16.0 Simulator

除了通过这个弹窗查看系统里有哪些 iOS 模拟器外,还可以在命令行运行 xcrun simctl list devices 指令查看。

其它

具体安装方式见官网。

Watchman 2022.11.14.00,使用 Homebrew 安装即可。

第二阶段:初始化项目

初始化项目前,确保当前系统应用了上述环境,一一检查一遍,否则创建项目环节就会失败,比如,初始化项目时会检查 Ruby 版本,RN 0.70.6 需要 Ruby 2.7.5,在命令行中执行 rvm use ruby-2.7.5 即将 Ruby 运行时切换到版本 2.7.5。

使用 npx react-native init --npm joker 指令初始化初始化项目。这里强制使用 NPM 包管理器,如此不破坏 npm 使用习惯,不会引入新的学习成本,如果不介意学习成本,可以无障碍引入比 Yarn 性能更好的包管理器:PNPM。参阅《pnpm 是凭什么对 npm 和 yarn 降维打击的》。

运行 npx react-native init --npm joy 指令后,会提示使用 gem 还是 homebrew 安装 CocoaPods,优选 gem。

目前并不会对项目内容做过多修改,重心:成功运行起来。

第三阶段:启动项目前准备工作

检查开发环境

进入项目根目录,执行 npx react-native doctor 指令主动检查开发环境,

Common
 ✓ Node.js
 ✓ npm
 ✓ Watchman - Used for watching changes in the filesystem when in development mode

Android
 ✓ JDK
 ✓ Android Studio - Required for building and installing your app on Android
 ✓ Android SDK - Required for building and installing your app on Android
 ✓ ANDROID_HOME

iOS
 ✓ Xcode - Required for building and installing your app on iOS
 ✓ CocoaPods - Required for installing iOS dependencies
 ● ios-deploy - Required for installing your app on a physical device with the CLI
 ✓ .xcode.env - File to customize Xcode environment

如果有问题,可以根据指令的提示自动修复开发环境。

最后,运行 npx react-native info 输出开发环境信息,再确认一遍,

System:
    OS: macOS 12.6.1
    CPU: (8) x64 Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
    Memory: 265.16 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.12.1 - ~/.nvm/versions/node/v18.12.1/bin/node
    Yarn: 1.22.10 - ~/.nvm/versions/node/v18.12.1/bin/yarn
    npm: 9.1.2 - ~/.nvm/versions/node/v18.12.1/bin/npm
    Watchman: 2022.11.14.00 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.11.3 - /Users/iyowei/.rvm/gems/ruby-2.7.5/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 22.1, iOS 16.1, macOS 13.0, tvOS 16.1, watchOS 9.1
    Android SDK:
      API Levels: 31
      Build Tools: 30.0.3, 31.0.0
      System Images: android-31 | Google APIs Intel x86 Atom_64
      Android NDK: 25.1.8937393
  IDEs:
    Android Studio: 2021.3 AI-213.7172.25.2113.9123335
    Xcode: 14.1/14B47b - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.17 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 18.1.0 => 18.1.0
    react-native: 0.70.6 => 0.70.6
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

都符合 ::预期::,继续推进。

启动模拟器

启动 Xcode,并不需要打开任意项目,找到 Xcode 菜单栏,顺序 “Xcode -> Open Developer Tool -> Simulator” 操作即可打开模拟器。 D2354363-FD36-4D60-9A11-6062936696DC.png

但是默认打开的模拟器运行的 iOS 系统、设备型号不一定是期望的,这也是可以切换的,找到 Simulator 菜单栏,顺序 “Simulator -> Open Simulator -> 选择期望的 iOS 版本 -> 选择期望的设备型号” 操作即可切换模拟器。 4F1A5E92-7686-414F-BC59-7F26AE59867B.png

启动 Metro

待模拟器启动成功后,进入项目根目录,在单独的命令行会话中,执行 npx react-native start 指令启动 Metro 服务。 945FD924-CF18-40D6-97BB-BF7D8A371CD3.png

第四阶段:启动项目

准备好了开发环境,模拟器也打开了,启动好了 Metro,都没问题,就可以启动项目。

推荐用 xcode 构建、运行项目,而非命令行

找到项目中 ios 目录下的 “fk.xcworkspace” 文件,双击用 xcode 打开,确定顶部工具栏显示的模拟器参数符合第三阶段预先打开的模拟器后,在 xcode 中点击运行按钮,xcode 便开始构建、运行项目。

不推荐通过命令行(npx react-native run-ios --simulator "iPhone 14 (16.1)" --port 8889)的方式运行项目,缘由目前是我自己猜的:某些文件的编译需要 xcode 来负责,而非命令行,前者的权限能做更多命令行不能及的事。另外,上手 RN 项目的纯前端同学对原生部分不太了解,原生相关的事让 IDE 操作,会得多。

一般来说,Xcode 在 RN 开发活动中,就是充当了构建、发布、编辑原生代码的作用,实际编写 React 的过程还是在 VS Code 这类编辑器中。

之后,第二次启动,或是开发中需要不停重启,推荐先前清理缓存再启动应用,

  • 清空 xcode 构建缓存,快捷键是 Command + Shift + K;
  • 清空模拟器数据,找到 Simulator 菜单栏,顺序 “Device -> Erase All Content and Settings” 操作即可;(不同版本的 Xcode 下模拟器的菜单可能不同位置不同)

如果项目运行出了问题,使用上述清除缓存的方式后依然不顺利,可以尝试清除 Xcode 的 DerivedData 目录(rm -rf ~/Library/Developer/Xcode/DerivedData/*),这里存放着所有临时构建信息和项目索引,清除后将强制 Xcode 在下次运行时重新创建它们。

如果需要让项目从全新的状态重新来过,除了要完成上述清理缓存的事情,还可以将 metro、watchman、cocoapods、npm 的缓存以及后两者安装的依赖全部清空,之后再重新安装,为了方便、快速,将这一步的操作整理成清单,

  • npx react-native clean --include 'cocoapods,metro,npm,watchman,yarn'
  • npm i / yarn install,看项目使用的是哪一款;
  • cd ios && pod install;(如果修改 Podfile 了,比如禁用了 hermes、flipper 等依赖,每次都需要重新操作 pod install
  • cd ../,返回项目根目录;

清缓存到了这一步,不妨重启系统后,再运行项目,🤪。

第五阶段:Flipper 调试

Flipper 不仅提供了 JS 的调试工具,还集成了 react-devtools、网络监测、崩溃监测、模拟器管理等工具。如果只是调试 JS 的话,也可以使用借助 Google Chrome 开发者工具实现,这里不赘述,因为操作很简单。

Flipper 需要单独安装,但是使用它还需要配置一下环境:fb-idb、OpenSSL。

安装 fb-idb 前需要先部署好 Python >= 3.6 环境,实测安装最新 Python 也是可以的。推荐使用 pyenv 安装 Python,这是 Python 的版本管理工具。pyenv 的安装方式具体参见 官方文档

前面的开发环境也提到了 OpenSSL,Flipper 直接沿用,但是可能会报 “Can’t open /usr/lib/ssl/openssl.cnf” 错误,一般是因为不存在这个文件,创建它就好了。先查找(find / -iname openssl.cnf)系统内其它位置有没有 openssl.cnf 文件,有的话复制到 /usr/lib/ssl/openssl.cnf,没有的话,就拷贝 OpenSSL 项目里的 openssl.cnf 文件模板

现在启动 Flipper,打开的界面上可能会报一些警告。暂时先不管这些。找到 Flipper 左下角,顺序 “点击左下角设置按钮 -> Settings” 操作打开如下界面,并按照下图所示配置 Flipper。IDB 可执行未见的位置通过 which idb 指令获得。设置好之后,点击 “Apply and Restart” 即可。 31322D17-7B43-4770-9775-7A2ADE8D7FA5.png

重启 Flipper 后,点击左下角 “Seup Doctor” 按钮(图标按钮,鼠标放上去就可以看到提示),检查 Flipper 的运行环境是否准备妥当,全部通过的话,如下图所示。 74B9DDA2-F753-484C-8231-13988506676F.png

到这里,可以开始正常使用 Flipper 了。一般来说,先启动项目的 Metro 服务,再打开 FlipperFlipper 会立马识别出来虚拟机或真机设备,之所以能够识别,就是因为 fb-idb 的作用:链接 iOS 与 Flipper 的桥梁。

第六阶段:真机调试

用 xcode 打开项目中的 "./ios/joker.xcworkspace”。

双击左侧文件树中的 “joker”,打开项目信息界面,顶部选项卡切换到 “Signing & Capabilities”。参照下图所示。 FB9437AE-9F88-47F0-A097-2AB5A0FB5692.png

此时是没法儿真机调试的,因为缺少开发团队配置,包标识符可能也不合法,没有证书等。点击 “Add Account” 按钮,输入 Apple ID,然后 Apple 会自动将这个 Apple ID 添加进个人团队里。 Frame 1.png

同时,为该开发者团队生成证书。 Frame 1.png

点击 Done 后,弹窗会关闭,此时为 ”Team” 属性选择刚才创建的开发者团队即可。再修改下 “Bundle Identifier” 属性,只需要在后头增加一个后缀即可,即: org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier).ck

此时项目的属性是可以真机构建了,但是手机上还有一些配置。

打开 Xcode 的同时,用数据线将手机同电脑直连。此时在 Xcode 中顺序 “Product -> Destination” 操作,可以看到刚才有线直连电脑上的手机在 “Unavaliable Device” 栏目里。识别除了设备,但是标识为无效,是因为手机还没开启开发者模式。 1E268560-A110-4F0E-A3EA-28AD4138FBB0.png

数据线不要断开,在手机上顺序 “设置 -> 隐私与安全性 -> 开发者模式 -> 激活” 操作,手机会重启一次,重启后手机就打开了开发者模式。切记不要断开数据线,否则手机上是不会显示 “开发者模式” 这个选项的。 Frame_1.jpg

回到 Xcode,顺序操作 “Product -> Destination” 菜单,可以看到设备不再被标识为无效。手动选中连接到 Xcode 的设备。

4243FAAC-8739-4DF3-B55D-AC87DB8C10D6.png

运行项目,Xcode 会自动将 joker 这款应用安装到手机上,并且在 “设置” 的首页可以看到冒出一个独立的 “开发者” 菜单。

但是,会失败,😆。 A4871979-350E-4DD5-8BC6-B3A4A39CFB22.png

手机上也会弹窗提示无法运行该应用。 9245FEA4-69EE-4D4D-94D7-EAF3A32E61D2.png

这是因为没配置手机信任这款应用。

在手机上顺序 “设置 -> 通用 -> VPN 与 设备管理 -> 开发者 APP -> 信任” 操作即可。

Frame_1.jpg

配置信任后,就可以顺利运行了。配合 Flipper 一起使用,开始真机调试。

第七部分:生产打包

顺序操作 “Product -> Destination -> Any iOS Device”,设置模拟器为 “Any iOS Device”, 截屏2022-11-28 11.05.11.png

或者直接操作顶部状态栏里的设备也行, 截屏2022-11-28 11.06.47.png

设置模拟器为 “Any iOS Device” 后,顺序操作 “Product -> Archive”,即开始构建、打包,成功后会打开如下弹窗, 截屏2022-11-28 11.25.22.png

右键该 Archive,在 Finder 中打开其位置, 截屏2022-11-28 11.25.35.png

存档后缀名是 .xarchive,右键可查看其中内容, 截屏2022-11-28 13.43.33.png

顺序打开 “Products -> Applications”,即可看到后缀名为 .app 的文件, 截屏2022-11-28 13.44.24.png

在 "Products/Applications" 文件夹下,

  • 创建名为 “Payload” 文件夹;
  • 将后缀名为 .app 的文件拷贝进去;
  • Zip 压缩 “Payload” 文件夹,生成 Payload.zip 文件;
  • 按照 [应用名称].ipa 模式重命名 Payload.zip 文件,假设应用名为 ruff,即:ruff.ipa。

到此,就有了一个 iOS 安装包。 截屏2022-11-28 14.34.08.png

因为没有发布到 App Store 上,所以安装的方式会不太一样,得通过 iTunes、AnyTrans 一类的 iPhone 管理工具传输到手机上。 截屏2022-11-28 14.35.58.png

传输到手机上后,即安装成功,传输工具会自动识别它是个应用,要安装它。但是在手机上打开应用时,可能会遇到真机调试时遇到的信任问题,解决办法同真机调试处写到的一致,可以直接沿用。

后续后可以在 Xcode 菜单栏顺序操作 “window -> Organizer” 再查看 Archives 弹窗。

结语

到这里,大体的工作流闭环就走完了:项目环境、创建、启动、调试、打包、安装。“发布到 App Store” 的部分,本文暂不赘述。

RN 技术中虽然使用 React 那一套来开发界面,但为了不牺牲原生样式、体验,并且确保真正原生渲染,这导致底层渲染界面的原理、实现方式与浏览器不同,所以不能期望 RN 的开发方式会和 Web 开发完全一致,一定会有出入。在正式投入开发前,需要提前认识到这一点,不要 Web 的那一套牵绊,站在原生的角度,重新学习那些组件怎么使用、样式怎么编写、有哪些特性兼容性问题等等。

Facebook 对 RN 的 严重依赖,以及越来越多的重要科技巨头 使用 它,意味着 RN 将在可预见的未来继续蓬勃发展。

附言一

打算将我的笔记都以文章的形式发布出来,与大家分享,更多(80%)还是想交流,集思广益,另外也想结识些志趣相投的新朋友,好朋友,🫵🏼,我知道你就在那儿,快联系我吧!😬(微信:iyoooooooo