从源码构建 Expo Go:在 Expo 开源仓库中搭建环境、编译 Android/iOS 宿主应用与排障实战
【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo
Expo Go 是运行 Expo SDK 实验性/最新功能的宿主 iOS 与 Android 应用,但它并不是供普通用户从源码编译的普通模板工程。本指南基于仓库内 guides/Developing Expo Go.md 与其权威正文 apps/expo-go/README.md,完整讲解在 macOS 上从零配置 Expo 开发环境、编译 Expo Go Android/iOS 包、启动 Metro 加载 Native Component List 测试页的全过程,并给出.cxx构建产物清理、gradlew clean、git clean三档排障手段;同时结合 package.json、Brewfile、scripts/download-dependencies.sh 等仓库文件,说明每一步背后的源码依据。读完你即可在自己的机器上跑通一次完整的 Expo Go 源码构建。
先厘清文档入口:本指南的正文位置
仓库中 guides/Developing Expo Go.md 本身只有一句话:"This guide was moved to the Expo Go Readme."(本指南已迁移至 Expo Go 的 Readme)。也就是说,这份开发指南的权威正文位于 apps/expo-go/README.md,其内容覆盖以下主题:
- Introduction(为何需要源码构建)
- External Contributions(外部贡献边界)
- Configuring your environment(环境配置)
- Building Expo Go(Android / iOS 构建)
- Troubleshooting(排障)
本文以 apps/expo-go/README.md 为骨架,逐条展开并补入仓库源码层面的佐证。
什么场景才需要从源码构建 Expo Go
apps/expo-go/README.md 开头便做了重要澄清:
- 如果你只是想在模拟器或真机上安装 Expo Go 使用,完全不需要从源码构建,直接通过 Expo 官方渠道(如 expo.dev/go 提供的下载页)安装现成客户端即可。
- 如果你要开发的是自定义图标、自定义名称的独立 App,应使用 EAS Build 或本地构建管线,而不是修改 Expo Go 源码。
- 如果你需要为自己的 Expo 项目增加自定义原生模块等 native 改动,应创建 development build(开发构建),而不是改造 Expo Go。
- 如果你希望为 Expo SDK 本身贡献代码、开发并测试改动,默认应该使用仓库内的 apps/bare-expo 应用,除非你的改动只针对 Expo Go 应用本身。
这段"边界澄清"极其重要:Expo Go 源码构建的目标受众是Expo Go 应用与 SDK 自身的维护者/贡献者,其产物是一个内置了全部 Expo SDK 原生能力的宿主 App(仓库中 apps/expo-go/package.json 一次性依赖了 camera、calendar、sqlite、video、notifications 等大量expo-*workspace 包即可佐证),并非用来承载任意第三方业务工程的容器。
另外,在向 Expo Go 提交 Pull Request 之前,官方建议先在社区(如 Discord)与维护团队沟通确认,避免无效劳动。
配置构建环境
平台与前置工具
官方明确:仅在 macOS 上支持构建 Expo Go。环境准备步骤(对应 apps/expo-go/README.md 的 "Configuring your environment"):
安装 direnv 与 Homebrew。
克隆本仓库。官方建议克隆到完整路径不含空格的目录,并且必须带上全部子模块:
git clone --recurse-submodules <本仓库地址>子模块是构建的关键前提——仓库的 React Native 版本正是以 Git 子模块形式存放在
react-native-lab目录中(详见下文)。在仓库根目录执行
brew bundle。根目录 Brewfile 的内容印证了它的必要性:Expo Go 经由 react-native-lab 设置了RCT_BUILD_HERMES_FROM_SOURCE,需要从源码编译 Hermes,因此必须安装cmake与ninja。在仓库根目录执行
pnpm install。本仓库是 pnpm workspace 管理的 monorepo(根 package.json 中workspaces.packages覆盖apps/*、packages/*、packages/@expo/*等),并对工具链版本有硬性要求(engines.node为^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0,engines.pnpm为^10.33.0),请先核对本机 Node/pnpm 版本。在仓库根目录执行
pnpm setup:native。在
packages/expo目录执行pnpm build,先把核心 SDK 包构建出来,供上层应用引用。
setup:native到底做了什么
从根 package.json 可以看到:
"setup:native": "./scripts/download-dependencies.sh --native && ./scripts/setup-react-android.sh",download-dependencies.sh --native(scripts/download-dependencies.sh)会先校验node、npm、direnv是否可用;随后执行git submodule update --init与git submodule foreach --recursive git checkout .初始化全部子模块;若pnpm不存在则通过npm install -g pnpm安装,最后执行pnpm install。也就是说该脚本覆盖了"子模块初始化 + 依赖安装"两件事。setup-react-android.sh(scripts/setup-react-android.sh)负责 Android 侧准备:定位sdkmanager(优先使用 PATH 中的命令,否则回退到$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager,仍不可用则提示先通过 Android Studio 安装 SDK 与 Command-Line Tools);自动接受 Google 许可证、安装 emulator 与 platform-tools、NDK 等组件。因此执行前请保证sdkmanager可被找到(或将ANDROID_SDK_ROOT环境变量指向正确的 SDK 根目录)。
提示:
setup-react-android.sh中具体安装的 NDK / platform / build-tools 组件版本会随仓库演进而变化,实际以你 clone 到的仓库版本为准;排障时若遇到 Android SDK 组件缺失,优先对照该脚本确认预期组件。
构建 Expo Go
第 1 步:准备 React Native
Expo Go 的 React Native 依赖并不直接来自 npm registry,而是来自react-native-lab子模块。在 monorepo 根目录执行:
pnpm install:react-native-lab该命令对应根 package.json 的脚本:在react-native-lab/react-native目录执行yarn install --frozen-lockfile(目录为空时会跳过并给出提示),再构建react-native-codegen。
react-native-lab/README.md 解释了这套设计的由来:react-native-lab/react-native是指向expo/react-nativefork 的 Git 子模块,fork 保持在与上游 React Native 稳定版非常接近的sdk-*分支上;改动若能合入上游,会优先通过 PR 回到facebook/react-native,Expo 只在必要时少量 cherry-pick 关键修复,以保证 fork 永远可以被上游版本替换。这正是 Expo Go 能"边跑最新 SDK、边贴近上游 RN"的工程基础。
(可选)若要单独验证 React Native Android 原生侧,可在react-native-lab/react-native目录执行:
./gradlew :packages:react-native:ReactAndroid:buildCMakeDebug该步骤并非必须——构建 Expo Go 时会顺带构建 React Native,但提前单独编译有助于把"RN 原生问题"与"Expo Go 工程问题"隔离排查。
第 2 步:Android 构建
在apps/expo-go/android目录执行:
./gradlew app:assembleDebug这会产出 Debug 版 Expo Go APK。从 apps/expo-go/package.json 的expo.autolinking配置可见,Expo Go 的模块自动链接搜索路径包含../../react-native-lab/react-native/packages、./node_modules与../../node_modules(并排除@expo/home自身)——这解释了为何前面必须先初始化react-native-lab子模块并安装依赖,否则 autolinking 会找不到 RN 相关包。
第 3 步:iOS 构建
在apps/expo-go/ios目录先安装 Pod 依赖:
pod install然后打开工作区(注意是Exponent.xcworkspace而非.xcodeproj):
open ios/Exponent.xcworkspace在 Xcode 中选择模拟器或真机运行即可。由于 Expo Go 的 iOS 侧会从源码编译 Hermes(见前文 Brewfile 中RCT_BUILD_HERMES_FROM_SOURCE的说明),首次构建耗时较长属正常现象。
启动 Metro 并加载 Native Component List
Expo Go 本体只是"宿主外壳",真正用于验证各组件效果的界面来自仓库内的 apps/native-component-list 应用(该目录下有超过 500 个覆盖各 Expo 模块演示页面的src/**/*.tsx)。启动方式:
cd apps/native-component-list EXPO_SDK_VERSION=UNVERSIONED npx expo start --clearEXPO_SDK_VERSION=UNVERSIONED表示使用仓库中的未发布(unversioned)SDK 源码进行开发验证,而不是拉取某个已发布 SDK 版本——这正是维护者在自己仓库里测试最新 SDK 改动的核心用法。- 启动后用上一步构建的 Expo Go 扫描二维码即可打开 Native Component List;也可以在 Metro 终端里按
i(iOS)或a(Android)直接在已安装的 Expo Go 中打开。 --clear会清除 Metro 缓存,避免因 monorepo 内 workspace 包的符号链接导致缓存失真。
常见问题与三档排障手段
apps/expo-go/README.md 的 Troubleshooting 章节按严重程度从小到大给出了三种方案:
第一档:只清理.cxx构建产物若遇到 C++ 相关报错,多半是 CMake/Hermes 等本地 C++ 构建缓存损坏。可在仓库内执行:
find . -name ".cxx" -type d -prune -exec rm -rf '{}' +该命令会递归删除所有.cxx目录(Android 原生 C++ 构建缓存),随后重新构建通常即可恢复。
第二档:执行 Gradle clean构建前建议先清理工程:
./gradlew clean在apps/expo-go/android目录执行,清除 Gradle 的中间产物与旧 task 状态。
第三档:'nuke' 式彻底重置如果前两档无效,使用核选项:
git submodule foreach --recursive git clean -xfd git clean -xfd它会删除所有未跟踪文件(包括原生构建产物与下载的依赖),因此之后必须重新执行初始化脚本:
./scripts/download-dependencies.sh再重新构建,耗时会更长,但据文档描述"this approach appears to be effective"(该方法对顽固问题通常有效)。
常用命令速查
| 阶段 | 命令 | 执行位置 |
|---|---|---|
| 安装系统依赖 | brew bundle | 仓库根目录 |
| 安装 JS 依赖 | pnpm install | 仓库根目录 |
| 原生环境初始化 | pnpm setup:native | 仓库根目录 |
| 构建核心 SDK 包 | pnpm build | packages/expo |
| 安装 React Native Lab 依赖 | pnpm install:react-native-lab | 仓库根目录 |
| (可选)预编译 RN Android | ./gradlew :packages:react-native:ReactAndroid:buildCMakeDebug | react-native-lab/react-native |
| 构建 Android | ./gradlew app:assembleDebug | apps/expo-go/android |
| 安装 iOS Pod | pod install | apps/expo-go/ios |
| 运行 iOS | 在 Xcode 打开并运行 | apps/expo-go/ios/Exponent.xcworkspace |
| 启动 Metro 测试环境 | EXPO_SDK_VERSION=UNVERSIONED npx expo start --clear | apps/native-component-list |
| 清理 C++ 缓存 | find . -name ".cxx" -type d -prune -exec rm -rf '{}' + | 仓库内 |
| 清理 Gradle | ./gradlew clean | apps/expo-go/android |
| 彻底重置 | git submodule foreach --recursive git clean -xfd与git clean -xfd,随后重跑./scripts/download-dependencies.sh | 仓库根目录 |
延伸阅读指引
- apps/expo-go/README.md:本文对应的权威开发指南正文。
- apps/expo-go/package.json:Expo Go 宿主 App 的完整依赖清单与模块 autolinking 配置。
- react-native-lab/README.md:解释 React Native fork 子模块的维护策略与升级流程。
- package.json 与 Brewfile:monorepo 脚本定义与 macOS 系统依赖(cmake/ninja)。
- scripts/download-dependencies.sh 与 scripts/setup-react-android.sh:
pnpm setup:native的底层实现。 - apps/bare-expo:官方推荐的、面向普通 Expo SDK 贡献者的开发与测试应用。
- apps/native-component-list:用于验证 Expo Go 中各组件的演示应用。
需要再次提醒的是:Expo Go 的源码构建是维护者工作流的一部分,构建门槛与耗时都明显高于普通 Expo 工程;如果你的目标是安装使用 Expo Go、发布独立 App 或为自有工程添加原生模块,请回到"何时才需要从源码构建 Expo Go"一节确认你确实在正确的路径上。
【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考