Windows 或 Linux 可以承担大部分 React Native 编码,但 React Native iOS 打包中的原生依赖、Release 构建、签名和 Archive 必须交给能运行 Xcode 的远程 Mac;本周建议你先把项目同步到受控仓库,再完成一次“依赖恢复 → 构建 → 签名 → 上传”的可回退流程。

这篇教程适合三类人:

  • 在 Windows 或 Linux 上开发 React Native App,第一次需要生成 iOS 发布构建的独立开发者。
  • 使用 React Native CLI,或项目已经包含 ios 目录和原生模块的维护者。
  • 想把远程 Mac 固化为持续打包环境,而不是每次临时借机器的小型团队。

本文默认项目是 React Native CLI 项目,已经生成 ios 目录。Expo 托管构建不作为本文主流程。

01

先划分任务边界:原电脑编码,远程 Mac 发布

React Native 项目最容易踩的坑,是把“JavaScript 能在 Windows 或 Linux 上运行”误认为“整个 iOS 发布流程也能在 Windows 或 Linux 上完成”。

你可以继续在原电脑上处理:

  • JavaScript、TypeScript、状态管理和业务逻辑。
  • Metro 开发服务及大部分前端调试。
  • Android 构建和 Android 真机测试。
  • Git 分支、Pull Request、代码审查和版本记录。

需要转移到远程 Mac 的任务包括:

  • iOS 原生依赖解析和 CocoaPods 安装。
  • Xcode 工程、原生模块和 App Extension 编译。
  • iOS Simulator 调试和物理设备签名。
  • Release 构建、Archive、导出和上传。
  • App Store Connect 构建处理及 TestFlight 验收。

React Native 官方环境文档确认,iOS 构建需要 Xcode,同时涉及 Node、CocoaPods 和命令行工具。项目中的 .xcode.env 还可以用于固定 Xcode 构建脚本使用的 Node 路径。React Native 环境配置文档

先写清楚四个边界

在连接远程 Mac 之前,先把以下内容写进项目文档或发布清单:

  1. 源码从哪个仓库、哪个分支拉取。
  2. Bundle ID、Team、Scheme 和 Release 配置分别是什么。
  3. Apple 开发者账号由谁管理,谁可以操作签名资产。
  4. 最终实体设备测试由谁完成,不能把远程模拟器当作真机验收。

如果你还没有稳定的 Mac 环境,可以先了解 VpsMesh 的 Mac 远程租赁方案,但不要在第一步就把所有凭据复制到主机上。先让代码能干净恢复,再处理签名资产。

02

第一个小时固定环境:不要直接在主机上“修到能跑”

远程 Mac 的第一个小时,不应该用来反复删除缓存。你的目标是记录环境、固定入口,并保留回退点。

1.记录当前状态

在远程 Mac 上记录:

xcode-select -p
xcodebuild -version
node --version
ruby --version
pod --version
git rev-parse --short HEAD

项目名称、用户名、主机地址、路径、Bundle ID 和 Team ID 都应使用你自己的脱敏占位符保存。例如:

PROJECT_NAME
REPOSITORY_URL
BUNDLE_ID
TEAM_ID
REMOTE_MAC_USER

不要把 Apple 密码、私钥、App Store Connect API Token 或完整 Keychain 导出文件提交到仓库。

2.确认 Xcode 工具链

打开 Xcode,检查 Command Line Tools 是否指向当前使用的 Xcode。然后确认 iOS Simulator 组件已经安装。

如果远程 Mac 上安装了多个 Xcode,先指定开发者目录:

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

命令中的路径只是示例。你应替换为实际安装路径,并在切换前记录原值,避免影响同一主机上的其他项目。

3.固定 Node 入口

Xcode 的构建脚本不会总是读取你交互式终端里的 Node 环境。可以在项目的 .xcode.env 中设置:

export NODE_BINARY=/opt/homebrew/bin/node

不要直接照抄路径。用下面的命令确认实际位置:

which node

如果远程 Mac 使用 Node 版本管理工具,应确保 SSH 非交互会话也能找到同一个 Node。否则终端里执行 npm install 没问题,Xcode 的脚本阶段仍可能提示找不到 Node。

4.锁定依赖恢复方式

从受控仓库拉取代码后,根据项目实际文件选择一种包管理器:

npm ci

或者:

yarn install --frozen-lockfile

然后进入 iOS 目录:

cd ios
pod install

如果项目采用其他 CocoaPods 工作流,应以仓库中的文档和现有脚本为准。不要在远程主机上随意升级 Pod、Ruby 或 Xcode,然后再把生成的工程文件提交回主分支。

03

首次 Debug 构建:先证明项目能离开原电脑

第一次构建的目标不是发布,而是把问题分层。你需要分别验证 JavaScript、原生依赖、Xcode 编译和 Simulator 启动。

先恢复,再构建

建议按以下顺序执行:

git clone REPOSITORY_URL
cd PROJECT_NAME

npm ci
cd ios
pod install
cd ..

npx react-native run-ios

如果项目使用 Yarn,就保持全程使用 Yarn。不要在同一次恢复过程中混用多个锁文件。

使用 CocoaPods 的项目,通常应从 ios/PROJECT_NAME.xcworkspace 打开,而不是直接打开 .xcodeproj。否则 Pods 集成的库可能没有被正确加载。

把错误分成四层

✅ 依赖解析失败:检查锁文件、Podspec、Ruby 和网络访问。

✅ 原生模块编译失败:检查模块支持的 iOS 部署目标、Swift 或 Objective-C 编译错误,以及对应 Target 是否加入。

✅ JavaScript Bundle 失败:检查 Node 路径、Metro 配置和构建脚本使用的环境变量。

✅ Simulator 启动失败:检查已安装的模拟器运行时、Scheme 和目标设备。

React Native 的 Simulator 文档提供了通过命令启动项目,以及使用 xcrun simctl list devices 查看设备的方法。iOS Simulator 运行文档

模拟器能运行,只能证明 Debug 路径基本可用。它不能证明 Release 配置、签名、Archive 或真实设备权限没有问题。

04

首次 Release 构建:先处理工程,再处理签名

Release 构建失败时,最常见的问题不是“远程 Mac 性能不够”,而是 Scheme、Target、Bundle ID 和签名状态不一致。

先核对原生工程

在 Xcode 中逐项检查:

  • 当前 Scheme 是否指向主 App,而不是测试 Target。
  • 构建配置是否为 Release。
  • 主 App 和 App Extension 是否使用正确的 Bundle ID。
  • Team 是否属于当前 Apple 开发者账号。
  • Capabilities 是否与开发者后台配置一致。
  • 所有需要签名的 Target 是否都配置了有效签名方式。
  • 构建号是否比上一次上传的构建号更高。

发布前还应确认 Bundle ID、版本号、构建号、图标和启动画面。Bundle ID 用于唯一识别 App,配置错误时,即使本地 Build 成功,上传阶段也可能被拒绝。发布前工程检查文档

自动签名还是手动签名

小团队首次发布时,优先考虑 Xcode 自动管理签名。这样可以减少证书、Provisioning Profile 和设备注册之间的手工对应关系。

如果团队需要严格控制签名资产,再考虑手动管理。无论使用哪种方式,都要先定义回退方式:

  • 自动签名失败:恢复上一个可用的 Team 和 Bundle ID 配置。
  • 手动签名失败:保留旧的 Provisioning Profile 和证书指纹。
  • Keychain 出现异常:不要直接删除全部证书,先导出诊断信息。
  • App Extension 签名失败:单独检查 Extension 的 Bundle ID 和 Capabilities。

签名资产不是普通依赖。它们一旦泄露,别人可能使用你的开发者身份分发软件。导出的签名身份必须受到保护。签名身份安全说明

05

首次 Archive:区分 Build、Archive 和导出资格

在 Xcode 中选择正确的 Scheme 和真机目标,然后执行:

Product → Archive

成功后,Archive 会出现在 Organizer 中。Apple 的分发流程将 Archive 作为上传 TestFlight 或发布 App 前的构建产物,也支持先执行 Validate App,再进行分发。Xcode 分发文档

你要分别记录三个结果:

  1. Build 成功:编译器完成当前配置的构建。
  2. Archive 成功:Xcode 生成可在 Organizer 中管理的归档。
  3. 导出或上传资格通过:签名、Bundle ID、版本信息和发布配置满足分发要求。

不要把第一个结果当成第三个结果。

Archive 前重点检查:

  • Run Destination 不是 iOS Simulator。
  • Scheme 使用 Release 配置。
  • 主 App 和所有附加 Target 都参与正确的构建。
  • 版本号和构建号符合 App Store Connect 当前记录。
  • 需要的符号文件能够随构建上传。
  • 构建日志已保存到脱敏目录。

示例日志目录:

artifacts/
├── environment.txt
├── pod-install.log
├── build-release.log
├── archive.log
└── upload.log

如果 Archive 失败,先根据失败 Target 定位。不要一上来执行大范围清理,因为清理会抹掉原本能帮助你判断问题来源的中间状态。

06

首次上传 TestFlight:上传完成不等于可以测试

首次上传前,你必须在 App Store Connect 创建 App 记录。上传构建前,Bundle ID、平台和应用信息必须与工程配置匹配。创建 App 记录说明

在 Xcode Organizer 中选择 Archive,然后执行:

Distribute App → TestFlight & App Store → Upload

上传后的验收顺序不要跳过:

  • Xcode 是否报告上传成功。
  • App Store Connect 是否收到构建。
  • 构建是否完成 Apple 服务器处理。
  • 版本号和构建号是否关联到正确的 App。
  • 是否出现缺少出口合规信息。
  • 构建是否变为可加入测试的状态。
  • 实体设备是否能通过 TestFlight 安装并运行。

上传成功不等于已经可以测试。构建仍需经过服务器处理,处理完成后才会出现在 App Store Connect 中,并根据 Bundle ID、版本号和构建号关联到对应 App。上传构建说明

App Store Connect 中的 Invalid Binary、Missing Compliance、Ready to Test 和 Testing 代表不同阶段。不要把其中任意一个状态直接当成“已经发布”。

TestFlight 支持内部测试和外部测试。官方资料显示,TestFlight 最多可邀请 10,000 名测试者,单个构建通常有 90 天测试可用期限;这两个数字属于平台规则,发生变化时应以当前官方说明为准。App Store Connect 总览

远程 Mac 可以完成构建和上传,但不能替你完成最终实体设备验收。推送通知、相机、定位、钥匙串、后台任务和真实网络环境,都应至少在一台实体 iPhone 上回归。

07

第一周维护:把一次成功变成可恢复流程

第一次上传成功后,不要马上认为环境已经稳定。你还需要模拟几种真实故障:

  • SSH 连接中断后,能否重新进入同一构建目录。
  • VNC 会话断开后,构建是否仍能查看日志。
  • 远程 Mac 重启后,Xcode 路径、Node 路径和 Keychain 是否恢复。
  • Pod 安装失败后,能否从锁文件回到已知状态。
  • 上传失败后,能否使用同一个 Archive 重试,而不是重新构建。
  • 主分支更新后,能否识别源码、依赖和签名配置的差异。

建议把流程拆成几个可重复任务:

restore-dependencies
build-debug
build-release
archive
validate
upload
save-logs

每个任务都写明:

  • 输入是什么。
  • 成功条件是什么。
  • 失败后在哪里停止。
  • 哪些文件可以清理。
  • 哪些签名资产绝对不能删除。

首次使用 Xcode 完成验收后,你还可以根据发布频率选择命令行工具、Transporter 或 API 上传构建。这样能把远程 Mac 从“手动操作的临时机器”逐步变成可追踪的发布节点。

用条件分支选择环境

  • 若只需要提交一次或偶尔处理一个版本:选择短期远程 Mac,完成依赖恢复、Archive 和 TestFlight 上传后保留日志。
  • 若每周都要发布,或项目包含多个原生模块:保留可复用的远程 Mac,固定 Node、CocoaPods、Xcode 路径和构建脚本。
  • 若多人共享同一发布流程:把源码访问、签名资产和上传凭据分开管理,不要让所有成员共用主账号。
  • 若构建需要长时间运行:优先使用 SSH 脚本和日志保存,远程图形会话只用于首次配置和异常排查。
  • 若必须频繁连接实体 iPhone 调试:远程 Mac 不一定合适,应保留本地 Mac 或安排专门的真机测试机。
  • 若项目长期稳定重负载构建:比较自购 Mac、常驻远程 Mac 和 CI 的总维护成本,不要只看一次打包价格。
08

常见问题

Windows 电脑可以完成 React Native 的 iOS 发布吗?

Windows 可以完成 JavaScript 开发、Git 管理和 Android 调试,但 React Native CLI 的 iOS 原生依赖、Xcode 编译、签名和 Archive 需要 macOS。正确做法不是把整个开发环境搬走,而是保留 Windows 作为编码电脑,把 ios 目录和锁定分支同步到远程 Mac,再在那里完成发布链路。

React Native iOS 构建是否必须使用 Mac?

对于包含原生 ios 工程、原生模块或发布签名的项目,需要能运行 Xcode 的 macOS 环境。你不一定要购买本地 Mac,但不能绕过 Mac 端工具链。远程 Mac 可以完成构建、签名和上传;不过,真实 iPhone 的安装、权限、推送和摄像头等功能仍应由实体设备完成验收。

远程主机上怎样恢复 CocoaPods 并生成归档?

先从受控仓库恢复源码和锁文件,再确认 Node、Xcode Command Line Tools、Ruby 与 CocoaPods。执行 pod install 后,从 .xcworkspace 打开项目,检查 Release Scheme、Bundle ID、Team 和 Capabilities,最后在真机目标下执行 Product > Archive。归档成功后,再从 Organizer 验证和分发。

React Native App 如何进入 TestFlight 测试?

先在 App Store Connect 创建 App 记录,然后从 Xcode Organizer 选择已经验证的 Archive,使用 TestFlight 分发选项上传。上传成功后要等待平台处理构建,再检查版本号、构建号、出口合规和测试状态。只有构建进入可测试状态,并且实体设备安装回归通过,才算完成一次有效验收。

09

远程 Mac 还是临时借机:发布频率决定答案

临时借用 Mac 的问题通常不在“能不能打包”,而在于环境不可复用:Node 和 CocoaPods 版本可能漂移,签名资产可能不完整,SSH 断线后日志难找,下一次发布还要重新安装依赖。若你只是处理一次提交,短期远程 Mac 已经足够;如果你持续维护 React Native 原生模块、每周发布,或需要固定的 iOS 打包服务器,就应保留可重连、可恢复的环境。

你可以先查看 VpsMesh 的 Mac mini M4 租赁与购买说明,再结合发布频率、真机测试责任和签名管理方式决定租期。不要为了省去一次配置而长期背负一台闲置硬件;也不要为了短期省钱,让每次发布都重新经历依赖安装和签名排错。