首页
/ Expo 仓库架构全景解读:Expo SDK、Modules API、CLI 与 EAS 的 Monorepo 组织方式

Expo 仓库架构全景解读:Expo SDK、Modules API、CLI 与 EAS 的 Monorepo 组织方式

2026-09-07 16:10:07作者:卓炯娓

本文基于 Expo 仓库根目录的 README 及其配套源码,系统讲解 Expo 这个"用 React 构建 Android、iOS 与 Web 通用原生应用"的开源平台的仓库结构、SDK 组成、测试应用矩阵与 Monorepo 工程化体系。读完后,你能快速定位仓库中任意组件(SDK 模块、CLI、模板、文档)的源码位置,理解各目录的职责边界,并掌握在本地构建、测试与贡献这套代码库的标准流程。

Expo 是什么

README 对 Expo 的定义是:一个构建通用原生应用的开源平台,应用可运行在 Android、iOS 和 Web 上;它提供一套通用运行时(universal runtime)和一系列库,让开发者只写 React 和 JavaScript 就能构建原生应用。

这个仓库(root 包名 @expo/expo,见 package.json)包含的内容包括:

此外,README 指出 Expo Application Services (EAS) 是一组与 Expo 开源工具深度集成的托管服务(构建、发布、迭代),面向个人与团队。注意 EAS 的服务端不在本仓库中,仓库内主要是与之配套的开源工具链。

仓库目录布局详解

README 的 "Project Layout" 一节是理解整个仓库的地图。下表在原文档基础上,结合仓库实际内容做了扩充:

目录 职责 补充说明
packages 所有 Expo 模块的源码 想修改某个库或研究其实现原理,从这里入手。expo-constantsexpo-imageexpo-router 等近百个包都在这里
apps 链接到开发中模块的 Expo 工程 日常开发测试主要在这里进行,apps/README.md 明确说明不要向本仓库新增 app,每个 app 都会增加维护成本
apps/expo-go Expo Go 客户端源码 开发 iOS 时必须打开 ios/Exponent.xcworkspace 而不是 Exponent.xcodeproj,因为 workspace 会同时加载 CocoaPods 依赖
docs https://docs.expo.dev 官网源码 基于 Next.js 构建,docs/README.md 描述了版本化文档的工作流
templates npx create-expo-app 使用的模板 包含 blank、blank-typescript、default、tabs、bare-minimum 五种模板
react-native-lab 用于构建 Expo Go 的 React Native fork README 称其为 "our fork of react-native",与上游仅保持必要的最小分叉
guides 高级主题的深入教程 例如 Expo Module Infrastructure、Generating Jest Mocks 等
tools 构建与配置工具 内含 expotoolset 命令)等内部 CLI 工具链
template-files 需要私有密钥的文件模板 template-files/keys.json 中的密钥填充

其中 template-files/ios/dependencies.json 专门指定了 bare-minimum 模板应用的 CocoaPods 依赖列表。

packages:SDK 的模块组成

packages/ 是仓库的核心,采用 pnpm workspaces 组织(见 pnpm-workspace.yaml,包匹配 packages/*packages/@expo/*)。从源码结构看,模块大致分为几类:

1. 基础 SDK 包(packages/expo。这是 "The Expo SDK" 本体,从 packages/expo/package.json 可以确认:

  • bin 字段暴露了三个可执行命令:expo(CLI 入口)、expo-modules-autolinking(模块自动链接)、fingerprint(应用指纹);
  • 核心依赖包括 @expo/cli@expo/config@expo/config-plugins@expo/metro-configbabel-preset-expoexpo-modules-core 等,全部以 workspace: 协议链接到本仓库内部版本——这正是 "SDK、CLI、Metro 配置统一发版" 的实现方式;
  • react/react-native 采用 * 的 peerDependencies,保证 SDK 可适配不同 RN 版本。

2. 功能模块(expo-*。每个模块都遵循统一目录约定,以 packages/expo-constants 为例:

  • src/:TypeScript 源码,编译输出到 build/(不提交 Git,由 Turborepo 按需构建与缓存);
  • ios/android/:原生侧实现(Swift/Kotlin 及 expo-module.config.json 声明的模块配置);
  • 常见 npm 脚本:buildtypechecktestlintformatdepscheck,由统一的 packages/expo-module-scripts 编排(CONTRIBUTING.md 中的 "Common package scripts" 一节有完整脚本表)。

3. 基础设施包(packages/@expo/*。包括 cli(命令行)、config / config-plugins(应用配置解析与配置插件)、metro-config / metro-file-map(打包器定制)、fingerprint(构建指纹)、doctor(诊断工具)等约三十个包。

4. 模块基础设施packages/expo-modules-core 提供了模块自动链接、JSI 桥接等底层能力;packages/expo-modules-autolinking 负责把 packages/ 中的原生模块自动织入 bare-expoexpo-go 等宿主工程。编写自定义模块的机制在 guides/Expo Module Infrastructure 中有完整说明。

apps:测试与验证应用矩阵

README 指出 "You'll do most of your testing in here"。apps/README.md 列出了仓库内 app 的官方定位:

  • bare-expo:裸 React Native 应用,链接 packages/ 中全部 SDK 依赖,用来运行 apps/test-suiteapps/native-component-list 的 JS 代码,是 SDK 开发的主力沙盒(CONTRIBUTING.md 明确推荐用 bare-expo 而非 Expo Go 做 SDK 开发,因为 Expo Go 需要 API token 且配置复杂);
  • Expo Goapps/expo-go):官方客户端 UI,包含完整的 Android/iOS 原生工程;
  • native-component-listapps/native-component-list):默认 Expo 预设中全部组件与 API 的展示清单,适合需要手动交互验证的 UI 测试;
  • test-suiteapps/test-suite):跑在设备/模拟器上的端到端测试集合,bare-expo 会导入它的根组件作为自身根组件;
  • sandboxapps/sandbox):本地实验项目,被排除在 Git 跟踪之外。

除这五个外,仓库还有若干专项工程:eas-expo-go(EAS 构建专用客户端)、minimal-testerobserve-testerrouter-e2e(expo-router 的端到端测试)、brownfield-tester(原生工程内集成 Expo 的混合场景测试,对应 packages/expo-brownfield)。

验证原生安装是否成功的标准流程(引自 CONTRIBUTING.md):

cd apps/bare-expo
pnpm ios        # iOS 模拟器
pnpm android    # Android 模拟器/设备

运行成功后,你就在 bare-expo 中跑起了 test-suite 应用;修改 SDK 包后无需重新打包 JS 部分,Metro 会热更新,但原生代码改动必须重新构建。

模板:create-expo-app 的起点

templates/ 目录保存了 npx create-expo-app 所用的项目模板,与 README 描述一一对应:

工程化体系:pnpm + Turborepo 的 Monorepo

README 只字未提构建体系,但理解仓库无法绕过它。从 package.jsonturbo.json 可以确认:

  1. 工作区定义:root package.jsonworkspacespnpm-workspace.yaml 共同声明了 apps/*packages/*packages/@expo/* 等范围;pnpm-workspace.yaml 还配置了 preferWorkspacePackages: true(优先链接工作区内同名包)与一份 patchedDependencies 补丁清单(对应仓库 patches 目录下的 .patch 文件,如 react-native-reanimatedreact-native-safe-area-context 等)。
  2. Turborepo 任务图turbo.json 定义了 build(依赖 ^build,按拓扑序构建并缓存 build/plugin/build/ 等输出)、typechecktestlintformat 任务,build 任务启用了 10GB 本地缓存与远端缓存。因此 root 的 pnpm buildpnpm testpnpm lint 会经 turbo 分发到所有工作区包并复用缓存。
  3. 环境约束engines 要求 Node ^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0、pnpm ^10.33.0CONTRIBUTING.md 另要求 Ruby 3.3+(iOS 侧)、推荐 JDK 17(Android 侧),且 Windows 需通过 WSL 开发。

Expo Go 徽章

README 提供了一个可直接复制的徽章,用于在你的项目中标识 "可在 Expo Go 中即时运行"。徽章源码为 shields.io 的 Runs with Expo Go 徽章(黑底与蓝底 4630EB 两个配色版本),README 中给出的 Markdown 片段原样保留如下,可粘贴到任何项目 README 中:

[![runs with Expo Go](https://img.shields.io/badge/Runs%20with%20Expo%20Go-000.svg?style=flat-square&logo=EXPO&labelColor=f3f3f3&logoColor=000)](https://expo.dev/client)

[![runs with Expo Go](https://img.shields.io/badge/Runs%20with%20Expo%20Go-4630EB.svg?style=flat-square&logo=EXPO&labelColor=f3f3f3&logoColor=000)](https://expo.dev/client)

学习路径与文档入口

README 的 Documentation 一节指向三块官方内容(均托管在 docs.expo.dev,其源码即本仓库 docs 目录):

  • Getting Started:从零创建、运行、发布应用的入门路径;
  • API Reference:按 SDK 版本归档的模块 API 文档,源码位于 docs/pages/versionsunversioned/ 为最新未发布版本,版本发布时由 docs/README.md 描述的工作流同步);
  • Using Custom Native Modules:自定义原生模块指南,对应仓库内 docs/pages/modules 与 guides/Expo Module Infrastructure。

仓库内 docs 目录本身就是一个 Next.js 工程,包含页面源(docs/pages)、MDX 插件(docs/mdx-plugins)、UI 组件(docs/ui)与文档质量检查脚本(docs/scripts,如链接协议校验、重定向检查等测试用例)。

贡献流程要点

README 指向 CONTRIBUTING.md 作为贡献入口。结合该文件,关键事实如下:

  1. 接收 PR 的范围packages/docs/templates/guides/apps/ 与 markdown 文件;通常不接收原生依赖版本号升级类 PR(由团队在发版流程中统一处理)。
  2. 本地开发循环cd packages/<包名> 编辑 src/pnpm build 编译 → 通过 bare-expo 在模拟器/真机验证;JS 改动可 expo start 热更,原生改动需重建。
  3. 测试三件套:包内 Jest 单元测试(src/__tests__/,桥接的新原生函数需在 jest-expo 中 mock,见 guides/Generating Jest Mocks)、apps/test-suite 中的端到端测试(新增文件需登记到 apps/test-suite/TestUtils.js)、native-component-list 中的手动演示用例。
  4. 提交前检查et check-packages <...packages>(等价于 CI 的 Turborepo 任务图);修改文档时需同步 docs/pages/versions/unversioned/ 下的对应版本文档;用户可见变更需记入所改包的 CHANGELOG.mdCHANGELOG.md
  5. 提交信息约定[platform][api] Title 格式,如 [ios][video] Fixed black screen bug...

许可证

按 README 说明:Expo 源码以 MIT 协议发布(见 LICENSE),部分第三方依赖采用其他协议(如 BSD),详见 THIRD-PARTY-LICENSES

小结

Expo 仓库是一个职责分层清晰的 Monorepo:packages/ 承载 SDK 与全部模块源码,apps/ 承载 Expo Go 与一整套测试沙盒,templates/ 承载开箱即用的项目起点,docs/guides/ 承载知识沉淀,tools/ 与根部的 pnpm workspaces + Turborepo 配置则把这些部分黏合成一个可增量构建、可缓存、可远端协作的工程体系。若你的目标是使用 Expo 开发应用,从 npx create-expo-app 生成的模板入手;若你的目标是研究或修改 Expo 本身,从 packages/expoapps/bare-expo 这两个入口开始,是效率最高的路径。

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

项目优选

收起
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
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
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
395