limrun-expo-development

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Developing Expo Apps on Limrun

在Limrun上开发Expo应用

Use this skill for Expo / React Native-specific setup and dev-client iteration. Use the generic Limrun iOS skill for command details, simulator interaction, screenshots, recordings, cleanup, and non-Expo iOS workflows.
All iOS builds and simulator operations must run on Limrun. Do not use local Xcode, local simulators, or local macOS build tools.
本技能适用于Expo/React Native专属的设置与开发客户端迭代流程。如需命令详情、模拟器交互、截图、录屏、清理以及非Expo的iOS工作流,请使用通用的Limrun iOS技能。
所有iOS构建和模拟器操作必须在Limrun上执行,不得使用本地Xcode、本地模拟器或本地macOS构建工具。

Expo Readiness

Expo就绪检查

Before changing Expo dependencies or app config, check the app's Expo SDK version and use the matching Expo versioned docs.
Verify this is an Expo app:
bash
npx expo config --type introspect --json
Derive:
  • BUNDLE_ID
    from
    ios.bundleIdentifier
  • SLUG
    from
    slug
  • SCHEME
    from
    scheme
    , falling back to
    exp+${SLUG}
  • BRANCH
    from
    git branch --show-current
    , falling back to
    main
  • ASSET_NAME="${BUNDLE_ID}/${BRANCH}-debug.zip"
在修改Expo依赖或应用配置前,请检查应用的Expo SDK版本,并使用对应版本的Expo文档。
验证当前项目是否为Expo应用:
bash
npx expo config --type introspect --json
提取以下信息:
  • ios.bundleIdentifier
    中获取
    BUNDLE_ID
  • slug
    中获取
    SLUG
  • scheme
    中获取
    SCHEME
    ,若不存在则回退为
    exp+${SLUG}
  • git branch --show-current
    中获取
    BRANCH
    ,若不存在则回退为
    main
  • ASSET_NAME="${BUNDLE_ID}/${BRANCH}-debug.zip"

Ensure Dev Client

确保安装开发客户端

Expo development builds require
expo-dev-client
. If it is missing from
package.json
, install it automatically:
bash
npx expo install expo-dev-client
Installing
expo-dev-client
, adding/removing/updating native dependencies, or changing native app config means the uploaded Debug asset is stale. Build a fresh Debug app before starting the dev loop. Do not merely warn the user that a rebuild may be needed; perform the rebuild.
Expo开发构建需要
expo-dev-client
。若
package.json
中未包含该依赖,请自动安装:
bash
npx expo install expo-dev-client
若安装了
expo-dev-client
、添加/移除/更新原生依赖,或是修改了原生应用配置,则已上传的Debug资源会失效。在启动开发循环前,请重新构建一个全新的Debug应用,仅告知用户可能需要重建是不够的,必须执行重建操作。

Debug Build Asset

Debug构建资源

First check whether a reusable Debug dev-client asset already exists:
bash
lim asset list --name-prefix "$BUNDLE_ID/"
Reuse the exact
$ASSET_NAME
only when:
  • it exists, and
  • no native dependency or native config changed in this session.
If the current task changed native dependencies or native config, skip asset reuse even if
$ASSET_NAME
exists.
When reusing the asset, create or reuse a simulator and install it:
bash
lim ios create \
  --reuse-if-exists \
  --install-asset "$ASSET_NAME" \
  --label repo=<repo> \
  --label agent=<agent>
When building fresh, create or reuse an iOS simulator with Xcode:
bash
lim ios create --xcode \
  --reuse-if-exists \
  --label repo=<repo> \
  --label agent=<agent>
If an iOS simulator is already running from a reused asset and a later native rebuild becomes necessary, attach or create Xcode for that same simulator instead of creating a second iOS simulator:
bash
lim xcode create --reuse-if-exists --label repo=<repo> --label agent=<agent>
lim xcode attach-simulator <ios-instance-id> --id <xcode-instance-id>
Then build and upload Debug:
bash
lim xcode build . \
  --configuration Debug \
  --upload "$ASSET_NAME"
Use
--expo-app-dir
,
--scheme
, or
--workspace
when the project layout requires it. A successful build installs and launches the app on the attached simulator.
首先检查是否存在可复用的Debug开发客户端资源:
bash
lim asset list --name-prefix "$BUNDLE_ID/"
仅在以下情况下才能复用指定的
$ASSET_NAME
  • 该资源确实存在,且
  • 当前会话中未修改原生依赖或原生配置
若当前任务修改了原生依赖或原生配置,即使
$ASSET_NAME
存在,也不能复用该资源。
复用资源时,创建或复用模拟器并安装该资源:
bash
lim ios create \
  --reuse-if-exists \
  --install-asset "$ASSET_NAME" \
  --label repo=<repo> \
  --label agent=<agent>
构建全新资源时,使用Xcode创建或复用iOS模拟器:
bash
lim ios create --xcode \
  --reuse-if-exists \
  --label repo=<repo> \
  --label agent=<agent>
若已复用资源启动了iOS模拟器,但后续需要进行原生重建,请为该模拟器附加或创建Xcode实例,而非创建第二个iOS模拟器:
bash
lim xcode create --reuse-if-exists --label repo=<repo> --label agent=<agent>
lim xcode attach-simulator <ios-instance-id> --id <xcode-instance-id>
随后构建并上传Debug资源:
bash
lim xcode build . \
  --configuration Debug \
  --upload "$ASSET_NAME"
若项目布局需要,可使用
--expo-app-dir
--scheme
--workspace
参数。构建成功后,应用会自动安装并启动在已附加的模拟器上。

Start Metro Tunnel

启动Metro隧道

Start Metro after the Debug app is installed:
bash
npx expo start --dev-client --tunnel
If
8081
is busy, choose a free port with
--port <port>
. If tunnel startup fails or exits, retry a few times; if it still fails, use the Limrun reverse fallback below. Keep Metro running while the user iterates.
Get the
https://*.exp.direct
tunnel URL from Expo output. If Expo does not print it, query the local ngrok API:
bash
curl -sS http://127.0.0.1:4040/api/tunnels
在Debug应用安装完成后启动Metro:
bash
npx expo start --dev-client --tunnel
若端口
8081
被占用,请使用
--port <port>
选择一个空闲端口。若隧道启动失败或退出,请重试几次;若仍失败,请使用下方的Limrun反向隧道作为备选方案。在用户进行迭代期间,请保持Metro持续运行。
从Expo输出中获取
https://*.exp.direct
格式的隧道URL。若Expo未打印该URL,请查询本地ngrok API:
bash
curl -sS http://127.0.0.1:4040/api/tunnels

Fallback: Limrun Reverse Tunnel

备选方案:Limrun反向隧道

If Expo's
--tunnel
repeatedly fails, use
lim ios reverse
with a matched remote/local port. Expo dev-client can derive or advertise multiple packager URLs, so mismatched mappings like
57090:8081
can leave some URLs pointing at the local Metro port instead of the simulator-facing tunnel port.
Use the simulator-facing host printed by
lim ios reverse
in both
REACT_NATIVE_PACKAGER_HOSTNAME
and the encoded dev-client URL. Keep the reverse command running in a separate or background terminal while Metro is running:
bash
lim ios reverse 57090:57090 --id <ios-instance-id>

REACT_NATIVE_PACKAGER_HOSTNAME=<reverse-host> \
  npx expo start --dev-client --host lan --port 57090

ENCODED_URL="$(node -e 'console.log(encodeURIComponent(process.argv[1]))' "http://<reverse-host>:57090")"
DEV_CLIENT_URL="${SCHEME}://expo-development-client/?url=${ENCODED_URL}"
lim ios open-url --id <ios-instance-id> "$DEV_CLIENT_URL"
若Expo的
--tunnel
参数反复失败,请使用
lim ios reverse
命令匹配远程/本地端口。Expo开发客户端可推导或广播多个打包器URL,因此像
57090:8081
这样不匹配的映射可能会导致部分URL指向本地Metro端口,而非模拟器面向的隧道端口。
请将
lim ios reverse
输出的模拟器面向主机同时用于
REACT_NATIVE_PACKAGER_HOSTNAME
和编码后的开发客户端URL。在Metro运行期间,请将反向命令保持在单独终端或后台运行:
bash
lim ios reverse 57090:57090 --id <ios-instance-id>

REACT_NATIVE_PACKAGER_HOSTNAME=<reverse-host> \
  npx expo start --dev-client --host lan --port 57090

ENCODED_URL="$(node -e 'console.log(encodeURIComponent(process.argv[1]))' "http://<reverse-host>:57090")"
DEV_CLIENT_URL="${SCHEME}://expo-development-client/?url=${ENCODED_URL}"
lim ios open-url --id <ios-instance-id> "$DEV_CLIENT_URL"

Launch Dev Client

启动开发客户端

Open the Debug app through the dev-client URL:
bash
ENCODED_URL="$(node -e 'console.log(encodeURIComponent(process.argv[1]))' "$TUNNEL_URL")"
DEV_CLIENT_URL="${SCHEME}://expo-development-client/?url=${ENCODED_URL}"
lim ios open-url "$DEV_CLIENT_URL"
If opening fails and the primary scheme came from
scheme
, retry once with
exp+${SLUG}
.
通过开发客户端URL打开Debug应用:
bash
ENCODED_URL="$(node -e 'console.log(encodeURIComponent(process.argv[1]))' "$TUNNEL_URL")"
DEV_CLIENT_URL="${SCHEME}://expo-development-client/?url=${ENCODED_URL}"
lim ios open-url "$DEV_CLIENT_URL"
若打开失败,且主scheme来自
scheme
参数,请使用
exp+${SLUG}
重试一次。

Verify

验证

For quick static validation, prefer:
bash
npx tsc --noEmit
Only run
npm run lint
or
npx expo lint
when the repo already has ESLint configured. Expo lint can create ESLint config and mutate dependencies in projects that have not configured linting yet.
Use the element tree first:
bash
lim ios element-tree
Success means the app UI is visible or the Expo dev menu shows it is connected to the tunnel. Dismiss the dev menu overlay if needed. If the tree does not confirm the connection, inspect app logs:
bash
lim ios app-log "$BUNDLE_ID" --tail 100
如需快速静态验证,优先使用:
bash
npx tsc --noEmit
仅当仓库已配置ESLint时,才运行
npm run lint
npx expo lint
。对于尚未配置代码检查的项目,Expo lint会创建ESLint配置并修改依赖。
优先使用元素树进行验证:
bash
lim ios element-tree
验证成功意味着应用UI可见,或Expo开发菜单显示已连接至隧道。若有需要,请关闭开发菜单覆盖层。若元素树未确认连接状态,请检查应用日志:
bash
lim ios app-log "$BUNDLE_ID" --tail 100

Iterating

迭代开发

Once connected, JS/TS edits should update through Metro without another native build. If the task changes native dependencies, native config, or build settings, rebuild Debug before relaunching the dev loop.
Tell the user:
  • simulator stream as a short Markdown link, for example
    [Open simulator stream](<signedStreamUrl>)
  • uploaded Debug asset name
  • that JS/TS changes can now iterate through Metro
  • that native changes require a new Debug build
连接成功后,JS/TS代码修改应通过Metro自动更新,无需再次进行原生构建。若任务修改了原生依赖、原生配置或构建设置,请在重启开发循环前重新构建Debug应用。
告知用户以下信息:
  • 模拟器流的短Markdown链接,例如
    [打开模拟器流](<signedStreamUrl>)
  • 已上传的Debug资源名称
  • 现在可通过Metro进行JS/TS代码的迭代开发
  • 原生代码修改需要重新构建Debug应用

Final Preview

最终预览

For a final shareable preview or PR demo, use a Release build so the user does not need Metro running:
bash
ASSET_NAME="<bundle-id>/<pr-or-session>.zip"
lim xcode build . --configuration Release --upload "$ASSET_NAME"
Preview URL:
text
https://console.limrun.com/preview?asset=${ASSET_NAME}&platform=ios
如需可分享的最终预览或PR演示,请使用Release构建,这样用户无需保持Metro运行:
bash
ASSET_NAME="<bundle-id>/<pr-or-session>.zip"
lim xcode build . --configuration Release --upload "$ASSET_NAME"
预览URL:
text
https://console.limrun.com/preview?asset=${ASSET_NAME}&platform=ios

Gotchas

注意事项

  • npx expo start --dev-client
    requires
    expo-dev-client
    ; without it Expo cannot determine the development-build scheme.
  • No script URL provided
    usually means the app is not a dev-client build or was launched without a dev-client URL.
  • After a fresh native rebuild/install, a stale Metro/runtime error like
    Cannot find native module
    may come from the old app process. Relaunch the dev-client URL and verify with
    element-tree
    before assuming the rebuild failed.
  • If a Debug build after adding a native dependency still behaves like the old native graph, that is unexpected Limrun behavior. Retry the build; creating a fresh iOS/Xcode target is only a troubleshooting fallback.
  • Expo tunnel startup can be flaky. Retry before changing the workflow.
  • Do not reuse uploaded Debug assets after native dependency or native config changes.
  • npx expo start --dev-client
    命令需要
    expo-dev-client
    依赖;若无该依赖,Expo无法确定开发构建的scheme。
  • 出现
    No script URL provided
    错误通常意味着应用不是开发客户端构建,或是未通过开发客户端URL启动。
  • 在全新原生重建/安装后,若出现
    Cannot find native module
    这类陈旧的Metro/运行时错误,可能是旧应用进程导致的。在假设重建失败前,请重新启动开发客户端URL并通过
    element-tree
    验证。
  • 若添加原生依赖后的Debug构建仍表现出旧原生图的行为,这属于Limrun的异常行为。请重试构建;创建全新的iOS/Xcode目标仅作为故障排查的备选方案。
  • Expo隧道启动可能不稳定,请在更改工作流前重试几次。
  • 修改原生依赖或原生配置后,请勿复用已上传的Debug资源。