关于 local-build
这项技能为 Expo 和 React Native 项目创建本地发布构建脚本,生成 Android APK 和 iOS 模拟器 .app。它从项目配置读取应用标识并调用平台工具链,产物路径固定,适用于本地测试和端到端测试。
主要功能
- 01生成 Android 发布 APK 脚本
- 02生成 iOS 模拟器 .app 脚本
- 03从 Expo 配置读取应用标识
- 04在固定路径替换构建产物
- 05将构建产物目录加入 .gitignore
适用场景
- 01构建 APK 以测试 Android 设备
- 02创建用于端到端测试的 iOS 模拟器版本
- 03为团队预览准备发布构建产物
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ code-with-beto/ skills --skill local-build安装后在 Claude Code 中输入/local-build确认已加载。
详细介绍
本地构建工作流(APK 和 .app)
概述
生成两个 Shell 脚本,直接使用平台工具链为 Expo / React Native 项目构建发布产物:
scripts/build-android.sh→ 运行./gradlew assembleRelease,并将 APK 复制到builds/scripts/build-ios.sh→ 为 iOS 模拟器运行xcodebuild,并将.app复制到builds/
每次运行时,两个脚本都会替换之前的产物,因此输出路径始终是可预测的。
存在这些脚本的原因: Expo 项目的调试构建包含 expo-dev-client,启动后显示“Development Servers”选择器,而不是应用界面。对于端到端测试、供队友预览或安装到真实设备,你需要 Release 构建,而这正是这些脚本生成的内容。
步骤 0:确认项目是 React Native / Expo 应用
在进行其他操作之前,确认当前目录是 Expo / React Native 项目:
- 检查
package.json中的dependencies是否包含expo。 - 检查是否存在
app.json或app.config.ts/app.config.js。
如果这两者都不存在,请停止并告知用户,此技能仅适用于 Expo 项目。
步骤 1:从 Expo 配置中读取应用标识信息
脚本需要三个特定于用户项目的值。不要硬编码 "YourApp",也不要假设应用名称。 请从配置中读取这些值。
要提取的值
| 值 | 查找位置 | 用途 |
|---|---|---|
name | app.config.ts / app.config.js / app.json → expo.name | iOS scheme 和 .app 文件名 |
slug | expo.slug | APK 文件名(备用值:小写的 name) |
ios.bundleIdentifier | expo.ios.bundleIdentifier | xcrun simctl launch 命令 |
android.package | expo.android.package | adb shell am start 命令 |
如何读取各种配置格式
app.json— 纯 JSON,直接解析。顶层键通常是expo。app.config.ts/app.config.js— 导出一个返回配置的函数。读取文件,并从返回的对象中提取字面值。不要尝试执行它。如果某个值是动态计算的,请询问用户要使用什么值。
确认磁盘上存在 iOS scheme
iOS scheme 文件是在 expo prebuild 期间根据 expo.name 生成的。将其写入脚本之前,请先确认它存在:
ls ios/*.xcworkspace 2>/dev/null
ls ios/*.xcodeproj/xcshareddata/xcschemes/*.xcscheme 2>/dev/null
.xcworkspace 名称和 .xcscheme 文件名(不含扩展名)是传给 xcodebuild -workspace 和 -scheme 的值。它们通常与 expo.name 相同,但如果不同,请使用磁盘上的实际值。
如果 ios/ 或 android/ 尚不存在,请运行:
npx expo prebuild
然后再次检查 scheme。
步骤 2:创建 Android 构建脚本
编写 scripts/build-android.sh。将 <SLUG> 替换为步骤 1 中的值。
#!/usr/bin/env bash
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(cd "$HERE/.." && pwd)"
ARTIFACT="$ROOT/android/app/build/outputs/apk/release/app-release.apk"
DEST_DIR="$ROOT/builds"
DEST="$DEST_DIR/<SLUG>.apk"
echo "==> Building Android release APK"
cd "$ROOT/android"
./gradlew assembleRelease
if [ ! -f "$ARTIFACT" ]; then
echo "Build did not produce $ARTIFACT" >&2
exit 1
fi
mkdir -p "$DEST_DIR"
rm -f "$DEST"
cp "$ARTIFACT" "$DEST"
echo "Done: $DEST"
注意:
- 必须使用
assembleRelease。assembleDebug会启动expo-dev-client,而不是应用。 - 如果项目未配置发布签名,Gradle 会回退到调试密钥库;这适合本地测试,但不能用于提交到 Play Store。
步骤 3:创建 iOS 构建脚本
编写 scripts/build-ios.sh。将 <SCHEME> 替换为步骤 1 中的值(它与 -workspace <SCHEME>.xcworkspace 和 -scheme <SCHEME> 使用的字符串相同,输出文件为 <SCHEME>.app)。
#!/usr/bin/env bash
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(cd "$HERE/.." && pwd)"
ARTIFACT="$ROOT/ios/build/Build/Products/Release-iphonesimulator/<SCHEME>.app"
DEST_DIR="$ROOT/builds"
DEST="$DEST_DIR/<SCHEME>.app"
echo "==> Building iOS Simulator .app (Release)"
cd "$ROOT/ios"
xcodebuild \
-workspace <SCHEME>.xcworkspace \
-scheme <SCHEME> \
-configuration Release \
-sdk iphonesimulator \
-derivedDataPath build \
CODE_SIGNING_ALLOWED=NO \
-quiet
if [ ! -d "$ARTIFACT" ]; then
echo "Build did not produce $ARTIFACT" >&2
exit 1
fi
mkdir -p "$DEST_DIR"
rm -rf "$DEST"
cp -R "$ARTIFACT" "$DEST"
echo "Done: $DEST"
注意:
-sdk iphonesimulator会生成模拟器用的.app,无法在实体设备上运行。CODE_SIGNING_ALLOWED=NO可安全用于模拟器构建,并且无需签名身份。.app是目录包,而不是文件,因此必须使用cp -R。
步骤 4:使脚本可执行
chmod +x scripts/build-android.sh scripts/build-ios.sh
步骤 5:将 builds/ 添加到 .gitignore
将以下内容追加到 .gitignore(先检查是否已存在):
# Local build artifacts
builds/
步骤 6:告知用户如何使用
向用户提供以下摘要:
Built two scripts for you:
./scripts/build-android.sh → builds/<slug>.apk
./scripts/build-ios.sh → builds/<scheme>.app
Install and run:
# Android (connected device or emulator)
adb install -r builds/<slug>.apk
adb shell am start -n <android.package>/.MainActivity
# iOS Simulator
xcrun simctl boot "iPhone 16" 2>/dev/null; open -a Simulator
xcrun simctl install booted builds/<scheme>.app
xcrun simctl launch booted <ios.bundleIdentifier>
生成消息时,将步骤 1 中的实际值代入,以便用户可以直接复制粘贴。
重要说明
- 使用 Release,而非 Debug。 Debug 构建会启动
expo-dev-client,显示带有“Development Servers”列表的启动器屏幕。若要查看实际 UI,必须使用 Release。 - 此处的 iOS 构建仅支持模拟器。 设备构建需要配置描述文件和签名身份,不在本技能的范围内。如果用户需要设备构建,请引导他们使用
eas build或手动进行 Xcode 归档。 - Android 仅使用调试密钥签名。 这个 APK 可用于本地测试和端到端测试,但不能用于提交到 Play Store。生产环境请配置发布密钥库,或使用
eas build。 - 配置值因项目而异。 不要硬编码“YourApp”或 Platano 示例中的值。务必从
app.config.ts/app.json中读取,并对照磁盘上的文件进行验证。
故障排除
“Build did not produce ...”
xcodebuild 或 gradlew 命令已成功运行,但产物不在脚本预期的位置。通常意味着:
- scheme 或 workspace 名称有误(检查
ios/*.xcworkspace和ios/*.xcodeproj/xcshareddata/xcschemes/) - 在构建脚本或 Gradle 覆盖配置中设置了自定义的
derivedDataPath或输出目录
xcodebuild: error: The workspace ... does not exist
运行 npx expo prebuild 以重新生成 ios/。如果已有 ios/ 文件夹,但其中没有 workspace,可能是 CocoaPods 安装失败了——运行 cd ios && pod install。
APK 安装成功,但打开后显示 expo-dev-client 启动器
说明脚本在执行过程中调用了 assembleDebug。请确保第 2 步的脚本调用 assembleRelease。
.app 打开后显示“Development Servers”
iOS 上也是同样的问题——脚本使用 -configuration Debug 而不是 Release 构建。请检查第 3 步的脚本。
xcrun simctl install 提示“incorrect executable format”
用户尝试在 macOS 上直接 open .app。模拟器的 .app 包只能在 xcrun simctl 中运行,不能作为 macOS 应用运行。请使用 xcrun simctl install booted <path> 命令。