返回首页
🎨 前端 / Web

React Native + Expo 实战:跨平台移动应用开发 2026

React Native + Expo 是 2026 年独立开发者首选跨平台方案。本文从 0 到生产级 App 上架,含 4 个实战项目 + 性能优化 + OTA 更新 + 变现。

React Native · Expo · 移动开发 · 跨平台 · iOS · Android · Hermes
📰

今日技术简讯

📰 技术简讯 · 2026-08-03

今日聚合 6 条热门技术内容(中文素材优先)。

🤖 AI / LLM

1. Expo 推出 AI SDK

  • 链接https://expo.dev/blog/ai-sdk
  • 来源:Expo
  • 摘要:Expo 推出 AI SDK,原生集成 Claude / OpenAI,设备端 + 云端混合推理。

2. React Native 0.78 推出 New Architecture 默认

  • 链接https://reactnative.dev/blog/0-78
  • 来源:React Native
  • 摘要:React Native 0.78 New Architecture 默认启用(Fabric + TurboModules),性能 +30%。

🎨 前端 / Web

3. EAS Build 推出 M4 Pro 加速

⚙️ 后端 / 架构

4. EAS Update 推出 OTA 实时更新

5. Hermes 引擎 1.5 推出

🚀 独立开发 / OPC

6. 即刻"React Native 独立开发"专题

  • 链接https://m.okjike.com/rn-indie-2026
  • 来源:即刻
  • 摘要:即刻 100+ 独立开发者分享 React Native 实战经验,跨平台 App / 性能优化 / 上架指南。

数据来源:掘金 / InfoQ 中文 / 即刻 / 少数派 / HN 采集时间:2026-08-03 09:00 (UTC+8)

📝

今日深度文

React Native + Expo 实战:跨平台移动应用开发 2026

一句话结论:React Native + Expo = 独立开发者的"App 神器"。一套代码 iOS + Android + Web,性能接近原生。本文从 0 到生产级 App 上架。

背景

2026 年跨平台移动开发格局:

React Native + Expo(首选)
├─ 一套代码,3 端发布(iOS / Android / Web)
├─ Hermes 引擎(启动 -30%)
├─ New Architecture(性能 +30%)
├─ EAS Build(云构建)
└─ EAS Update(OTA 秒级更新)

vs Flutter:性能强但 Dart 学习曲线
vs 原生:2 套代码,2x 成本

为什么 Expo 是独立开发者的首选:

  1. 零本地环境:无需 Xcode / Android Studio
  2. 云构建:EAS Build 自动打包
  3. OTA 更新:秒级发版
  4. Web 支持:一套代码 3 端
  5. 完整生态:Expo Modules + EAS + Router

6 大核心优势

1. Expo Router(文件路由)

// app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';

export default function TabsLayout() {
  return (
    <Tabs>
      <Tabs.Screen name="index" options={{ title: '首页' }} />
      <Tabs.Screen name="settings" options={{ title: '设置' }} />
    </Tabs>
  );
}

// app/(tabs)/index.tsx
import { View, Text } from 'react-native';

export default function Home() {
  return (
    <View>
      <Text>首页</Text>
    </View>
  );
}

2. EAS Build(云构建)

# 安装 EAS CLI
npm install -g eas-cli

# 登录
eas login

# 配置
eas build:configure

# 构建
eas build --platform ios    # iOS
eas build --platform android  # Android
eas build --platform all      # 同时构建
// eas.json
{
  "build": {
    "production": {
      "ios": {
        "distribution": "store"
      },
      "android": {
        "buildType": "app-bundle"
      }
    },
    "preview": {
      "distribution": "internal"
    }
  }
}

3. EAS Update(OTA 秒级更新)

# 发布更新
eas update --branch production --message "修复 Bug"

# 自动 OTA(无需应用市场审核)
// app.json
{
  "expo": {
    "updates": {
      "url": "https://u.expo.dev/xxxxx"
    },
    "runtimeVersion": "1.0.0"
  }
}

4. Hermes 引擎(性能 +30%)

// app.json
{
  "expo": {
    "jsEngine": "hermes"
  }
}

效果:

  • 启动时间 -30%
  • 内存占用 -25%
  • 包体积 -20%

5. NativeWind / shadcn(与 7/30 关联)

// Tailwind CSS 风格的 React Native
import { View, Text } from 'react-native';

export function Card() {
  return (
    <View className="bg-white rounded-lg p-4 shadow">
      <Text className="text-lg font-bold">标题</Text>
    </View>
  );
}

6. New Architecture(Fabric + TurboModules)

// 默认启用(React Native 0.78+)
// 性能提升:
// - 同步 UI 更新
// - 类型安全的 TurboModules
// - 共享 C++ runtime

4 个实战项目

项目 1:Todo App

// app/(tabs)/index.tsx
import { useState } from 'react';
import { View, Text, TextInput, Button, FlatList } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';

export default function TodoApp() {
  const [todos, setTodos] = useState<Todo[]>([]);
  const [input, setInput] = useState('');
  
  // 加载
  useEffect(() => {
    AsyncStorage.getItem('todos').then(data => {
      if (data) setTodos(JSON.parse(data));
    });
  }, []);
  
  // 保存
  const save = async (newTodos: Todo[]) => {
    setTodos(newTodos);
    await AsyncStorage.setItem('todos', JSON.stringify(newTodos));
  };
  
  // 添加
  const add = () => {
    if (!input.trim()) return;
    save([...todos, { id: Date.now(), text: input, done: false }]);
    setInput('');
  };
  
  return (
    <View className="flex-1 bg-white p-4">
      <View className="flex-row mb-4">
        <TextInput
          className="flex-1 border border-gray-300 rounded px-3 py-2 mr-2"
          placeholder="添加 Todo..."
          value={input}
          onChangeText={setInput}
        />
        <Button title="添加" onPress={add} />
      </View>
      
      <FlatList
        data={todos}
        keyExtractor={item => String(item.id)}
        renderItem={({ item }) => (
          <TodoItem
            todo={item}
            onToggle={() => save(todos.map(t => 
              t.id === item.id ? { ...t, done: !t.done } : t
            ))}
            onDelete={() => save(todos.filter(t => t.id !== item.id))}
          />
        )}
      />
    </View>
  );
}

项目 2:AI 聊天 App(与 7/29 WebGPU 关联)

// app/chat.tsx
import { useState } from 'react';
import { View, TextInput, Button, ScrollView, Text } from 'react-native';

export default function ChatScreen() {
  const [messages, setMessages] = useState<Message[]>([]);
  const [input, setInput] = useState('');
  const [loading, setLoading] = useState(false);
  
  const send = async () => {
    if (!input.trim()) return;
    
    const userMsg: Message = { role: 'user', content: input };
    setMessages([...messages, userMsg]);
    setInput('');
    setLoading(true);
    
    try {
      const res = await fetch('https://api.anthropic.com/v1/messages', {
        method: 'POST',
        headers: {
          'x-api-key': process.env.EXPO_PUBLIC_ANTHROPIC_API_KEY!,
          'anthropic-version': '2023-06-01',
          'content-type': 'application/json',
        },
        body: JSON.stringify({
          model: 'claude-sonnet-4-5',
          max_tokens: 1024,
          messages: [...messages, userMsg],
        }),
      });
      
      const data = await res.json();
      const assistantMsg: Message = {
        role: 'assistant',
        content: data.content[0].text,
      };
      
      setMessages([...messages, userMsg, assistantMsg]);
    } finally {
      setLoading(false);
    }
  };
  
  return (
    <View className="flex-1 bg-white">
      <ScrollView className="flex-1 p-4">
        {messages.map((msg, i) => (
          <View key={i} className={`mb-2 ${msg.role === 'user' ? 'items-end' : 'items-start'}`}>
            <View className={`max-w-[80%] rounded-lg p-3 ${msg.role === 'user' ? 'bg-blue-500' : 'bg-gray-200'}`}>
              <Text className={msg.role === 'user' ? 'text-white' : 'text-black'}>
                {msg.content}
              </Text>
            </View>
          </View>
        ))}
      </ScrollView>
      
      <View className="flex-row p-4 border-t">
        <TextInput
          className="flex-1 border rounded px-3 py-2 mr-2"
          value={input}
          onChangeText={setInput}
          placeholder="输入消息..."
        />
        <Button title={loading ? '...' : '发送'} onPress={send} disabled={loading} />
      </View>
    </View>
  );
}

项目 3:相机 App

// app/camera.tsx
import { CameraView, useCameraPermissions } from 'expo-camera';
import { useState } from 'react';
import { Button, Image, View } from 'react-native';

export default function CameraScreen() {
  const [permission, requestPermission] = useCameraPermissions();
  const [photo, setPhoto] = useState<string | null>(null);
  
  if (!permission) return <View />;
  
  if (!permission.granted) {
    return (
      <View className="flex-1 justify-center items-center">
        <Button title="授权相机" onPress={requestPermission} />
      </View>
    );
  }
  
  const takePhoto = async (camera: any) => {
    const photo = await camera.takePictureAsync();
    setPhoto(photo.uri);
  };
  
  return (
    <View className="flex-1">
      {photo ? (
        <Image source={{ uri: photo }} className="flex-1" />
      ) : (
        <CameraView className="flex-1">
          {({ camera }) => (
            <Button title="拍照" onPress={() => takePhoto(camera)} />
          )}
        </CameraView>
      )}
    </View>
  );
}

项目 4:电商 App

功能:
- 商品列表 + 详情
- 购物车 + 支付(Stripe)
- 用户认证
- 推送通知
- OTA 更新

技术栈:
- Expo Router
- NativeWind
- Supabase(后端,关联 7/15)
- Stripe(支付)
- Expo Notifications(推送)
- EAS Update(OTA)

5 个常见坑

坑 1:图片未优化

// ❌ 用普通 Image
<Image source={{ uri: 'https://example.com/photo.jpg' }} />

// ✅ 用 expo-image(自动优化)
import { Image } from 'expo-image';

<Image
  source="https://example.com/photo.jpg"
  contentFit="cover"
  transition={200}
  cachePolicy="memory-disk"
/>

坑 2:键盘遮挡

// ✅ 用 KeyboardAvoidingView
import { KeyboardAvoidingView, Platform } from 'react-native';

<KeyboardAvoidingView
  behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
  className="flex-1"
>
  {/* 内容 */}
</KeyboardAvoidingView>

坑 3:List 性能差

// ❌ 普通 map
{items.map(item => <Item {...item} />)}

// ✅ FlatList(虚拟列表)
<FlatList
  data={items}
  keyExtractor={item => item.id}
  renderItem={({ item }) => <Item {...item} />}
  initialNumToRender={10}
  maxToRenderPerBatch={10}
  windowSize={5}
/>

坑 4:无 OTA 降级

// app.json
{
  "expo": {
    "updates": {
      "checkAutomatically": "ON_LOAD",
      "fallbackToCacheTimeout": 5000  // 5 秒降级
    }
  }
}

坑 5:iOS 应用商店审核

App Store 审核拒绝常见原因:
- 缺少隐私政策
- 缺少登录功能(强制第三方登录)
- 缺少内容分级
- 测试账号无法登录
- 崩溃 / Bug

✅ 解决:EAS Submit + 完整元数据

上架指南

iOS App Store

# 1. EAS Build
eas build --platform ios

# 2. EAS Submit
eas submit --platform ios

# 3. App Store Connect
# 填写元数据 + 截图 + 审核

Google Play

# 1. EAS Build
eas build --platform android

# 2. EAS Submit
eas submit --platform android

# 3. Google Play Console
# 上传 AAB + 完整元数据

性能对比

| 方案 | 启动时间 | 内存 | 包体积 | 开发速度 |
|------|---------|------|--------|---------|
| React Native + Expo | 1.5s | 80MB | 30MB | ⭐⭐⭐⭐⭐ |
| Flutter | 1.2s | 70MB | 25MB | ⭐⭐⭐⭐ |
| 原生 (iOS + Android) | 0.8s | 60MB | 20MB | ⭐⭐ |
| PWA | 0.5s | 50MB | 0 | ⭐⭐⭐⭐⭐ |

与之前内容的关系

7/22 React 19 RSC          → Web 前端
7/23 10 大 AI 工具         → 工具
7/28 AI SaaS 月入 $10K     → 商业
7/29 WebGPU 浏览器端 AI    → 浏览器 AI
7/30 shadcn/ui 设计系统    → UI
7/31 Web 性能优化          → Web 性能
8/1 LLM 工程化             → AI 测试
8/2 Playwright + Vitest    → 测试
8/3 React Native + Expo    → 移动端  ← 今天
→ "Web → 测试 → 移动端"完整闭环

7 天落地路径

Day 1:初始化 Expo

npx create-expo-app my-app
cd my-app
npx expo start

Day 2:路由 + 导航

// app/(tabs)/_layout.tsx
// app/(tabs)/index.tsx

Day 3:UI 组件

npm install nativewind

Day 4:后端集成

// Supabase / API / 认证

Day 5:原生功能

// 相机 / 位置 / 通知

Day 6:构建

eas build --platform all

Day 7:上架

eas submit --platform all

我的看法

React Native + Expo 是 2026 年独立开发者的"App 神器"

  1. 跨平台:一套代码 3 端
  2. 零本地环境:无需 Xcode / Android Studio
  3. 云构建:EAS Build 自动
  4. OTA 更新:秒级发版
  5. 完整生态:EAS + Expo Modules + Router

对独立开发者的建议:

  • 新 App 首选:替代 Flutter / 原生
  • 快速原型:Expo + v0 + Cursor
  • OTA 更新:避免应用商店审核
  • Web + App:一套代码搞定

参考


本文基于 Expo SDK 53 + React Native 0.78,2026 年 8 月最新实战。

📚 同主题文章

🎨 前端 / Web 分类更多