Expo Development Build
1、为什么必须放弃 Expo Go
这是 Expo 学习体系中最核心、最具有分水岭意义的一个概念。理解了它,你就真正跨越了"玩具期",进入了"专业级跨平台开发"的领域。
我们先来破除一个常见的误区:放弃 Expo Go,绝不意味着放弃 Expo 框架本身! 你依然在使用 Expo 的路由、API 和打包服务,你只是不再使用那个名叫 "Expo Go" 的扫码 App 了。
那为什么必须放弃它?答案很简单:因为 Expo Go 是一个"写死了"的沙盒(Sandbox)。
当你从 App Store 或官网下载 Expo Go 时,你下载的是一个已经由 Expo 官方预先编译好的完整原生 App。在这个 App 的底层(iOS 的 Objective-C/Swift,Android 的 Java/Kotlin)里,官方帮你塞进去了几十种常用的原生模块(如相机、相册、位置等)。当你扫码时,Expo Go 只是把你的 JavaScript 代码下载下来,然后去调用它肚子里已经有的原生模块。
局限性
假设现在老板提了一个需求:"App 要接入微信登录,还要接入支付宝支付,推送要用极光推送。"
你兴冲冲地安装了 react-native-wechat-lib(微信 SDK),结果一跑,Expo Go 直接红屏崩溃了!为什么?因为微信 SDK 包含了微信自己写的原生代码(C++/Java/Objective-C),而你手机里的 Expo Go 是从应用商店下载的,它的肚子里根本没有微信的原生代码。
一个简单的判断标准:只要一个第三方库的文档里写着以下任意一条,它在 Expo Go 里就跑不起来:
- "请运行 pod install"(iOS 原生链接)
- "请修改 android/app/build.gradle"(Android 原生链接)
- "请在 AndroidManifest.xml 中添加特殊权限"
国内上架的硬性要求
如果你的 App 需要上架到华为、小米、OPPO、苹果等应用商店,还会遇到一个绕不开的问题:国内安卓应用商店有一个死规定——App 首次启动时,在用户同意《隐私政策》之前,绝对不能初始化任何获取设备信息的原生 SDK。
要实现这个拦截,你必须在安卓最底层的 MainApplication.kt 里写拦截逻辑,或者修改 AndroidManifest.xml。Expo Go 无法让你修改这些底层文件。
NOTE 总结:只要你的应用需要超出 Expo 官方提供的那几十个基础模块之外的原生能力(如微信、支付宝、各大厂商 SDK、特定硬件驱动、底层配置修改),你就必须放弃 Expo Go。
2、什么是 expo-dev-client
既然 Expo Go 跑不起来第三方原生 SDK,那传统的 React Native 开发是怎么做的?以前,大家会执行 expo eject(弹出),把项目变成一个纯原生项目,然后用 Android Studio 和 Xcode 去缓慢地编译。但这样做会彻底丢失 Expo Go 那种"扫码即看、极速热重载、错误提示友好"的开发体验。
为了解决这个痛点,Expo 官方推出了 expo-dev-client。
用一个比喻来理解:
- Expo Go 就像一辆公交车:路线固定,车里有什么配置早就定好了。你可以随时上车(扫码预览),但你不能要求司机把公交车改成敞篷跑车。
- expo-dev-client 就像是你自己打造的私家车:你想装什么引擎(微信 SDK、支付宝 SDK、极光推送)都可以。更妙的是,这辆私家车里安装了和公交车一模一样的"智能仪表盘"(即热重载、网络调试、扫码加载 JS 的能力)。
从技术角度来说,expo-dev-client 是一个 npm 包。当你把它安装到项目里,并进行一次原生构建后,它会生成一个专属于你这个项目的"定制版 Expo Go" App。在这个"定制版 App"里:
- 包含了你引入的所有第三方原生 SDK(比如微信、支付宝)
- 包含了你自己修改的原生配置(比如隐私弹窗拦截)
- 同时保留了开发菜单(摇晃手机呼出)、React 开发者工具、极速 Hot Reload 的能力
NOTE 构建完成后,这个 App 的图标默认会带有一个小齿轮标记,表示它是开发版。
3、安装与配置
安装 expo-dev-client
在你的 Expo 项目根目录下执行:
npx expo install expo-dev-client
这条命令会自动安装兼容当前 Expo SDK 版本的 expo-dev-client,并更新 package.json。
NOTE 使用
npx expo install而非npm install或yarn add,是因为 Expo CLI 会自动选择与当前 SDK 版本兼容的包版本,避免版本冲突。
生成原生工程(Prebuild)
安装完 expo-dev-client 后,你需要生成原生工程代码:
npx expo prebuild
这条命令会根据 app.json / app.config.js 中的配置,在项目根目录生成 ios/ 和 android/ 文件夹,包含完整的原生工程代码。
执行过程中,CLI 会提示你输入 iOS Bundle Identifier 和 Android Package Name(如果还没有在配置中指定的话):
? What would you like your iOS bundle identifier to be?
› com.yourname.myapp
? What would you like your Android package name to be?
› com.yourname.myapp
NOTE
prebuild是幂等操作。如果你修改了app.json中的配置,可以运行npx expo prebuild --clean重新生成原生工程。--clean会先删除现有的ios/和android/目录再重新生成。
在 app.json 中配置
确保你的 app.json 包含必要的配置项:
{
"expo": {
"name": "my-app",
"slug": "my-app",
"ios": {
"bundleIdentifier": "com.yourname.myapp",
"supportsTablet": true
},
"android": {
"package": "com.yourname.myapp",
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
}
},
"plugins": [
"expo-dev-client"
]
}
}
将 expo-dev-client 添加到 plugins 数组中,确保 prebuild 时正确注入开发工具。
4、构建与运行
本地构建
生成原生工程后,你可以直接在本地构建并运行:
iOS(需要 macOS + Xcode):
npx expo run:ios
Android(需要 Android Studio + SDK):
npx expo run:android
这些命令会:
- 编译原生代码,生成开发版应用
- 自动安装到模拟器或已连接的真机
- 启动 Metro 开发服务器
- 应用启动后自动连接到开发服务器
首次构建需要编译全部原生代码,后续构建会利用缓存显著加速。
NOTE 本地构建要求你已经配置好完整的原生开发环境(Xcode / Android Studio)。如果你不想配置本地环境,可以使用 EAS Build 在云端构建。
使用 EAS Build 云端构建
CAUTION 暂时仅做了解,后续会更详细的介绍 EAS Build
EAS(Expo Application Services)提供云端构建服务,无需本地原生环境。
第一步:安装 EAS CLI 并登录
npm install -g eas-cli
eas login
第二步:配置 EAS Build
eas build:configure
这会在项目根目录生成 eas.json 配置文件:
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal"
},
"production": {}
}
}
其中 development 配置项是专门为 Development Build 准备的:
developmentClient: true表示这是一个开发构建,会包含调试工具distribution: "internal"表示用于内部分发(不上架应用商店)
第三步:触发构建
# 构建 Android 开发版
eas build --profile development --platform android
# 构建 iOS 开发版
eas build --profile development --platform ios
# 同时构建双平台
eas build --profile development --platform all
构建完成后,EAS 会提供下载链接或二维码,直接安装到设备上。
启动开发服务器
Development Build 安装到设备后,启动开发服务器:
npx expo start --dev-client
然后在设备上打开你构建的应用,它会显示一个开发者菜单界面,你可以:
- 输入开发服务器地址手动连接
- 扫描终端中的二维码自动连接
- 从历史记录中选择最近连接过的服务器
连接成功后,开发体验与 Expo Go 完全一致——Fast Refresh、错误覆盖层、开发者菜单一应俱全。
5、开发工作流的变化
引入 expo-dev-client 后,你的开发流程会从以前的模式发生明显变化。
以前使用 Expo Go:
npx expo start启动开发服务器- 拿手机里的公共 Expo Go 扫码
- 只能写 JS 代码,不能加原生库
现在使用 Development Build:
- 安装第三方原生库(例如
npm i react-native-wechat-lib) - 安装 expo-dev-client:
npx expo install expo-dev-client - 构建定制 App(最关键的一步):执行
npx expo run:android或eas build --profile development - 把构建出的 App 安装到测试手机上
npx expo start --dev-client启动开发服务器- 打开你安装的"定制版 App",它会自动连接开发服务器,加载你的 JS 代码
现在,当你修改 JS 代码并按下保存时,画面依然会像 Expo Go 一样瞬间刷新;同时,当你的 JS 代码调用 Wechat.login() 时,它能完美地唤起原生微信,因为这个定制 App 的肚子里已经有微信 SDK 了。
何时需要重新构建
理解这个边界非常重要:原生代码变更时需要重新构建,但纯 JS/TS 变更不需要。
| 需要重新构建 | 不需要重新构建 |
|---|---|
| 安装/删除包含原生代码的库 | 修改 JS/TS/JSX/TSX 代码 |
| 修改 app.json 中的原生配置 | 修改样式、组件逻辑 |
| 添加或修改 Config Plugin | 安装纯 JS 包(如 lodash、dayjs) |
| 升级 Expo SDK 版本 | 修改 Metro 配置 |
NOTE 大部分开发时间你都不需要重新构建。只有涉及原生层变更时才需要。这让 Development Build 的日常体验和 Expo Go 非常接近。
6、总结
expo-dev-client 让你在保留 Expo 开发体验的同时,拥有完整的原生代码控制权。它是从"学习模式"迈向"专业开发"的关键一步。
行动指南:
- 在系统学习的前期,安心使用 Expo Go,因为它最简单、最快
- 当你需要接入第三方登录、支付、推送,或者处理国内上架的隐私合规时,就是你安装
expo-dev-client、打出第一个 Development Build 的时刻 - 放弃 Expo Go 不是放弃 Expo——你只是从公交车换成了私家车,路还是同一条路