React Native + Expo App 入门模板教程
零、技术栈选型
| 技术栈 | iOS | Android | 说明 |
|---|---|---|---|
| A. React Native | ✅ | ✅ | 一套代码双端运行,需 Mac 环境编译 iOS |
| B. Flutter | ✅ | ✅ | 一套代码双端运行,需 Mac 环境编译 iOS |
| C. Android 原生 | ❌ | ✅ | 仅安卓(Kotlin/Java) |
| D. iOS 原生 | ✅ | ❌ | 仅苹果(Swift) |
| E. 纯 Web 模拟 | ✅ | ✅ | 浏览器打开,非原生安装包 |
本教程选择 A. React Native + Expo:一套代码双端运行,无 Mac 时可先出 Android 包,后期有 Mac 后零修改编译 iOS。
一、环境准备
1.1 必备工具
| 工具 | 用途 | 安装方式 |
|---|---|---|
| Node.js v20+ | 运行 JS 环境 | nodejs.org |
| npm | 包管理器 | 随 Node.js 安装 |
| Expo Go | 手机扫码预览 | App Store / Google Play |
| EAS CLI | 云端打包 APK/IPA | npm install -g eas-cli |
1.2 验证环境
node -v # 应为 v20+ 或 v22+
npm -v # 确认 npm 可用
二、创建项目
2.1 初始化
npx create-expo-app@latest my-app --template blank
cd my-app
2.2 安装常用依赖
# 导航
npx expo install @react-navigation/native @react-navigation/native-stack react-native-screens react-native-safe-area-context
# WebView
npx expo install react-native-webview
⚠️ 必须用
npx expo install而非npm install,前者会自动匹配 Expo SDK 兼容版本,避免构建失败。
2.3 安装后验证
npx expo-doctor
三、项目结构
my-app/
├── App.js # 主入口,路由配置
├── app.json # Expo 配置(应用名、scheme、图标等)
├── eas.json # EAS Build 打包配置
├── package.json # 依赖管理
├── assets/ # 静态资源
│ ├── icon.png
│ ├── splash-icon.png
│ ├── adaptive-icon.png
│ └── favicon.png
└── node_modules/
四、核心代码模板
4.1 App.js — 首页 + WebView + Deep Link
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import WebView from 'react-native-webview';
// 首页
function HomeScreen({ navigation }) {
return (
<View style={styles.container}>
<StatusBar style="auto" />
<Text style={styles.welcome}>欢迎</Text>
<TouchableOpacity
style={styles.button}
onPress={() => navigation.navigate('WebView')}
>
<Text style={styles.buttonText}>打开百度</Text>
</TouchableOpacity>
</View>
);
}
// WebView 页面
function WebViewScreen() {
return (
<WebView source={{ uri: 'https://www.baidu.com' }} startInLoadingState={true} />
);
}
const Stack = createNativeStackNavigator();
// Deep Link 配置
const linking = {
prefixes: ['myapp://'],
config: {
screens: {
Home: 'home',
WebView: 'webview',
},
},
};
export default function App() {
return (
<NavigationContainer linking={linking}>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} options={{ title: '首页' }} />
<Stack.Screen name="WebView" component={WebViewScreen} options={{ title: '百度' }} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center' },
welcome: { fontSize: 28, fontWeight: '700', marginBottom: 40 },
button: { backgroundColor: '#3071F2', paddingVertical: 14, paddingHorizontal: 48, borderRadius: 24 },
buttonText: { color: '#fff', fontSize: 17, fontWeight: '600' },
});
4.2 app.json — 应用配置
{
"expo": {
"name": "my-app",
"slug": "my-app",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"splash": {
"image": "./assets/splash-icon.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"scheme": "myapp",
"ios": { "supportsTablet": true },
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
}
},
"web": { "favicon": "./assets/favicon.png" }
}
}
关键字段说明:
| 字段 | 作用 |
|---|---|
name | 应用显示名称 |
slug | 项目唯一标识(用于 Expo 云端) |
scheme | Deep Link URL Scheme,如 myapp:// |
splash | 启动屏配置 |
ios.supportsTablet | 是否支持 iPad |
android.adaptiveIcon | Android 自适应图标 |
4.3 eas.json — 打包配置
{
"cli": { "version": ">= 13.2.0" },
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal",
"android": { "buildType": "apk" }
},
"production": {}
}
}
构建类型说明:
| Profile | 输出格式 | 用途 |
|---|---|---|
preview | APK | 直接安装测试 |
development | 开发版 | 含开发工具 |
production | AAB | 上架 Google Play |
五、开发调试
5.1 启动开发服务器
npx expo start
5.2 手机预览
- 手机安装 Expo Go App
- 扫描终端二维码
- 修改代码自动热更新
5.3 常用命令
npx expo start --android # 启动并连接 Android 模拟器
npx expo start --ios # 启动并连接 iOS 模拟器(需 Mac)
npx expo start --web # 浏览器预览
六、Deep Link 使用
6.1 URL 映射
| URL | 页面 |
|---|---|
myapp://home | 首页 |
myapp://webview | WebView 页 |
6.2 唤起方式
从 HTML 网页唤起:
<a href="myapp://webview">打开App</a>
从 Android 终端测试:
adb shell am start -a android.intent.action.VIEW -d "myapp://webview"
从 iOS 终端测试(需 Mac):
xcrun simctl openurl booted "myapp://webview"
开发模式下 scheme 为
exp+项目slug://,正式打包后为app.json中配置的scheme://。
七、打包发布
7.1 前置准备
# 安装 EAS CLI(首次)
npm install -g eas-cli
# 登录 Expo 账号(首次)
eas login
# 如果没有账号,去 https://expo.dev/signup 注册
7.2 构建 Android APK
eas build --platform android --profile preview
- 首次会提示 Generate a new Android Keystore? → 输入
yes - 云端编译约 10-15 分钟
- 完成后输出 APK 下载链接
7.3 构建 iOS(需 Mac)
eas build --platform ios --profile preview
7.4 构建生产版(上架)
eas build --platform android --profile production # 输出 AAB
eas build --platform ios --profile production # 输出 IPA
八、常见问题
Q1: eas build 失败,提示 "Install dependencies" 错误
原因:package.json 中缺少依赖或版本不兼容。
解决:
# 用 expo install 确保版本兼容
npx expo install react-native-webview @react-navigation/native @react-navigation/native-stack react-native-screens react-native-safe-area-context
# 检查依赖一致性
npx expo-doctor
# 重新构建
eas build --platform android --profile preview
Q2: npm install 装到了父级目录
原因:npm hoisting 机制,如果父目录有 node_modules,依赖会被提升。
解决:确认 package.json 的 dependencies 中包含所有需要的包,即使 node_modules 在父级,EAS 构建时以 package.json 为准。
Q3: Node.js v18 下 MCP/Figma 报 ESM 模块错误
解决:升级到 Node.js v20+ LTS。
Q4: Expo Go 扫码连不上
- 确保手机和电脑在同一 Wi-Fi 下
- 尝试切换为隧道模式:
npx expo start --tunnel
九、快速复用清单
新建一个 App 只需:
# 1. 创建项目
npx create-expo-app@latest my-new-app --template blank
cd my-new-app
# 2. 安装依赖
npx expo install @react-navigation/native @react-navigation/native-stack react-native-screens react-native-safe-area-context react-native-webview
# 3. 替换 App.js(用上面的模板)
# 4. 修改 app.json(name / slug / scheme)
# 5. 创建 eas.json(用上面的模板)
# 6. 启动开发
npx expo start
# 7. 打包
eas build --platform android --profile preview