首页
/ Folo(follow)移动端预览构建安装指南:基于 EAS Local Build 与 devicectl 的真机 iOS 安装流程

Folo(follow)移动端预览构建安装指南:基于 EAS Local Build 与 devicectl 的真机 iOS 安装流程

2026-09-08 09:48:58作者:宣海椒Queenly

导读

本文以 Folo(follow)开源仓库中的 Agent 技能文档 installing-mobile-preview-builds 为主线,系统讲解如何在 macOS 上为 apps/mobile 移动应用构建一套全新的 preview(预览)本地 iOS 包,并将其安装到已连接的 iPhone 上用于类生产环境测试。读完本文,你将掌握从环境校验、设备选择、EAS 本地构建、IPA 解包安装到应用启动与故障处理的一整条可复现命令行流程,并能理解该流程背后与仓库中 eas.json、Expo 应用配置及资源预构建插件的对应关系。

技能定位与适用场景

.agents/skills/installing-mobile-preview-builds/SKILL.md 是仓库为 AI Agent(如 Claude/Copilot 类编码助手)提供的一个可调用技能文件,其 frontmatter 明确声明了它的行为边界:

  • description:当用户要求"在已连接的 iPhone 上安装 preview/internal iOS 构建包用于类生产测试"时触发;
  • disable-model-invocation: true:禁止模型在未经用户许可的情况下自动调用;
  • allowed-tools:仅允许 BashReadGlobGrep 四类工具;
  • argument-hint:可选的设备标识参数 [device-udid-or-name]

因此该技能适用于如下场景:不借助 TestFlight、不需要等待 EAS 云端队列,而是在开发机上直接产出 preview 渠道的本地安装包,并通过 Apple 的 devicectl(新一代命令行设备管理工具)完成真机安装与启动,用于发布前的最终体验验证。

流程总览:一条命令链贯穿的五个阶段

整条流程可以归纳为五个阶段,对应技能文档中的五个 Workflow 步骤:

  1. 环境与登录校验:确认仓库结构、pnpm/xcrun/xcodebuild/eas-cli 可用性以及 EAS 登录态;
  2. 目标设备解析:枚举已配对设备,按参数精确匹配 > 首台已配对 iPhone 的顺序选出安装目标;
  3. 触发本地 preview 构建:使用 EAS Local Build 产出 .ipa
  4. 本地安装到设备:解包 IPA 后通过 devicectl device install app 安装;
  5. 启动验证:通过 devicectl device process launch 尝试拉起应用并确认激活状态。

下面逐一展开。

第一步:仓库与工具链校验

1.1 校验仓库布局与包管理器

该技能要求所有命令从仓库根目录开始执行,并确认 apps/mobile 目录存在。这是本仓库 pnpm workspace 布局所决定的:apps/mobile(包名 @follow/mobile,见 apps/mobile/package.json)是 Expo React Native 应用的主目录,其内部还嵌套了 web-appweb-app/html-renderer 两个 workspace 子包(见 pnpm-workspace.yaml)。

1.2 校验系统工具

流程要求在 PATH 中存在以下四个命令:

命令 作用 缺失时的典型表现
pnpm workspace 包管理与依赖安装、执行 EAS CLI command not found: pnpm
xcrun 调用 Xcode 命令行工具(含 devicectl 提示需要安装 Xcode Command Line Tools
xcodebuild 参与 iOS 原生编译链路 需要安装完整 Xcode 及 iOS 平台支持
eas-cli Expo Application Services 命令行入口,通过 pnpm dlx eas-cli 临时拉取 网络不通时无法拉取

1.3 校验 EAS 登录态

进入 apps/mobile 后执行:

cd apps/mobile
pnpm dlx eas-cli whoami

该命令会返回当前登录的 EAS 账号。构建过程需要将产物与 EAS 项目绑定,本项目在 apps/mobile/app.config.base.ts 中通过 extra.eas.projectIda6335b14-fb84-45aa-ba80-6f6ab8926920)与 owner: "follow" 完成关联,未登录或登录账号无权访问该项目时会在此步失败。

第二步:解析目标设备

2.1 枚举已配对设备

xcrun devicectl list devices

该命令输出当前 Mac 上所有经信任配对的 Apple 设备及其 UDID、名称、状态。devicectl 是 Xcode 15+ 引入的、用来取代老式 ios-deploy/ideviceinstaller 的官方设备控制工具,本文后续的安装与启动都依赖它。

2.2 设备选择优先级

技能文档规定按以下顺序确定 <device-id>

  1. 若通过 $ARGUMENTS(即调用技能时的可选参数)传入了 UDID 或精确设备名,且与列表中的设备恰好唯一匹配,则使用该设备;
  2. 否则自动选择第一台已配对的 iPhone(注意不是 iPad,因为 preview 构建目标是 iOS 真机)。

第三步:触发本地 preview iOS 构建

3.1 构建命令

mkdir -p .context/preview-install
cd apps/mobile
pnpm dlx eas-cli build -p ios --profile preview --non-interactive --local --output=./build-preview.ipa
cd ../..
cp apps/mobile/build-preview.ipa .context/preview-install/folo-preview.ipa

逐个拆解关键参数:

  • -p ios:只构建 iOS 平台;
  • --profile preview:选用 EAS 构建配置中名为 preview 的 profile;
  • --non-interactive:禁止交互式提问,适合自动化/Agent 调用;
  • --local在本地机器上执行完整构建(本地模式会调用本机 Xcode 工具链,不占用 EAS 云端队列),这也是"preview 真机内部测试"能快速完成的关键;
  • --output=./build-preview.ipa:将最终产物写到 apps/mobile/build-preview.ipa
  • 最后复制到仓库根的 .context/preview-install/folo-preview.ipa 统一归档。

3.2 preview profile 的底层配置

preview profile 在 apps/mobile/eas.json 中定义:

"preview": {
  "distribution": "internal",
  "channel": "preview",
  "env": {
    "PROFILE": "preview"
  }
}
  • "distribution": "internal":产物为内部分发包,不面向 App Store,无需上传审核,可直接安装到注册设备;
  • "channel": "preview":对应 Expo Updates 的 OTA 更新通道(项目更新服务地址为 https://ota.folo.is/manifest,见 apps/mobile/app.config.base.ts),让该包可通过 expo-updates 接收 preview 通道的远程更新;
  • PROFILE=preview 环境变量会传导到 Expo 配置解析层。

3.3 PROFILE 环境变量如何影响 App 配置

apps/mobile/app.config.base.ts 中通过 process.env.PROFILE 驱动多处差异化配置,这是理解 preview 包与正式包差异的关键:

  • 渠道映射channelNameMap):previewpreview 通道,写入 Updates 请求头 expo-channel-name
  • 图标切换iconPathMap):preview 使用 assets/icon-staging.png(staging 图标,便于与生产包肉眼区分),而 production 使用 assets/icon.png
  • 开发类插件:当 process.env.PROFILE !== "production" 时会额外注入 plugins/android-trust-user-certs.js(信任用户自签证书的调试插件);
  • App 身份:iOS bundleIdentifier 固定为 is.followapps/mobile/app.config.base.ts),Android package 同为 is.follow。该标识后续启动命令会直接用到。

此外非 production 的 preview 构建会走完整原生编译(expo-build-properties 配置了 deploymentTarget: "16.4"useFrameworks: "static" 等),因此要求本机具备完整 Xcode 环境。

第四步:解包并安装到设备

4.1 解包 IPA

IPA 本质上是一个 ZIP 归档,内含 Payload/<AppName>.app 目录。使用系统 unzip 解包:

unzip -q -o .context/preview-install/folo-preview.ipa -d .context/preview-install/unpacked

参数说明:-q 静默模式;-o 覆盖已存在文件(保证重复执行时的幂等性)。

4.2 定位 .app 目录

APP_PATH=$(find .context/preview-install/unpacked/Payload -maxdepth 1 -name '*.app' -type d | head -n 1)

findPayload 下仅检索一层(-maxdepth 1),取第一个 .app 类型目录作为安装源;head -n 1 防止多 app 场景下变量被多行污染。

4.3 执行安装

xcrun devicectl device install app --device "<device-id>" "$APP_PATH"
  • --device "<device-id>" 传入第二步解析出的设备标识;
  • 该命令将 .app 签名安装到设备。若设备被锁屏或未信任此 Mac,会在此步骤失败。

第五步:启动应用并验证

xcrun devicectl device process launch --device "<device-id>" is.follow --activate
  • is.follow 是应用的 bundle identifier;
  • --activate 表示启动后将应用带到前台激活。

技能文档同时记录了兜底策略:如果启动失败是因为设备处于锁屏状态,则应引导用户解锁 iPhone 并手动打开 Folo——这是因为自动化启动受设备锁屏策略限制,属于正常现象而非安装故障。

失败处理与恢复路径

5.1 本地构建失败的报告格式

eas-cli build --local 阶段失败,技能要求按固定格式上报三类信息,便于快速定位:

  1. build mode(固定为 local);
  2. failing command(失败的命令原文);
  3. key error message from command output(命令输出中的关键错误信息)。

5.2 资源目录缺失:Assets source directory not found ... /out/rn-web

这是一个高概率出现的已知问题。Folo 移动端把 Web 端阅读渲染器构建产物作为内嵌静态资源打进原生包:配置文件 apps/mobile/plugins/with-follow-assets.jsprebuild 阶段检查 assetsPath(即仓库根下 out/rn-web),若目录不存在会先尝试自动执行 pnpm --dir ${webAppDir} build --outDir ...,仍失败则抛出:

Assets source directory not found! Please make sure the build is successful. path: .../out/rn-web

技能文档给出的手动恢复命令为:

pnpm --filter @follow/rn-micro-web-app build --outDir out/rn-web/html-renderer

需要说明其与仓库结构的对应关系:

  • @follow/rn-micro-web-app 正是 workspace 包 apps/mobile/web-app/package.json 的包名;
  • 其下层的 apps/mobile/web-app/html-renderer/package.json@follow/rn-micro-web-app-html-renderer)定义了真正的 Vite 构建入口,vite.config.mts 将构建产物输出到仓库根级 ../../../../out/rn-web/html-renderer
  • with-follow-assets.js 随后在 iOS 工程中把整个 out/rn-web 注册为名为 Assets 的 Xcode group / build file,在 Android 中拷贝到 app/src/main/assets,从而让原生 WebView 能通过本地资源渲染 HTML。

执行成功后重试一次 preview 构建即可。

输出格式:可审计的结果汇报

无论成败,技能都要求最终返回以下五项结构化信息,便于人工复核与后续操作衔接:

  1. Build modelocal)与最终状态(成功/失败);
  2. 本地 IPA 路径(即 .context/preview-install/folo-preview.ipa);
  3. 目标设备标识(UDID 或名称);
  4. 安装结果installed / failed)与启动结果;
  5. 若需人工介入,下一步动作(例如"解锁手机后手动打开 Folo")。

小结与可复用要点

  • 这套流程的本质是 EAS Local Build(--local)+ devicectl 的组合:前者把 preview 内部分发包的构建完全放到本地执行,后者用 Apple 官方工具链完成安装与启动,二者都不依赖 TestFlight 与云端队列,非常适合发布前的真机验收;
  • preview 渠道在 apps/mobile/eas.json 中与 development(开发客户端)和 production 隔离,并通过 PROFILE 环境变量在 apps/mobile/app.config.base.ts 中驱动图标、更新通道与插件差异,因此"preview 构建"并非简单的参数开关,而是一整套经过配置矩阵设计的产物变体;
  • 若在 CI/Agent 中复现,请特别注意两点:先完成 EAS 登录校验;若遇 Assets source directory not found,先执行 pnpm --filter @follow/rn-micro-web-app build --outDir out/rn-web/html-renderer 预生成 Web 渲染资源再重试。

需要复现上述全部命令时,可从仓库根目录执行技能原文 SKILL.md 中记录的完整命令序列;相关配置均可直接在 apps/mobile 目录下查阅、验证。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
858
1.35 K
docsdocs
暂无描述
Markdown
899
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
923
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.83 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
532
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
524
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
393