Expo vs Bare React Native 对比

借助 Node.js LTS 即可搭建、通过 CNG 实现可逆的 managed React Native 框架

VS
Bare React Native

在 native 工具链上拥有完全控制权的核心 React Native 搭建方式

16 分钟阅读Cross-Platform

快速结论

2026 年的默认答案是 Expo + CNG:由于 `expo prebuild` 可以重新生成 native 文件夹,“eject”不再是单向的门;config plugin 体系能覆盖大部分 native 配置需求,EAS Build 的免费层级也足以满足中小型项目。选择 Bare React Native 的理由虽然范围较窄但确实存在:EAS 不支持的特殊工具链、必须使用 on-prem CI,或是极其罕见的 native SDK。如果这三者都不成立,就从 Expo 开始。

ExpoBare React Native
阅读完整结论

评分对比

图表加载中…

详细评分

详细评分: Expo Bare React Native ——按类别打分,满分 10 分
分类ExpoBare React Native
性能
8/10
8/10
学习难易度
9/10
6/10
生态系统
8/10
8/10
社区
8/10
8/10
就业市场
7/10
8/10
面向未来
8/10
7/10

优缺点

Expo

优点

  • 搭建只需要 Node.js LTS——无需 Xcode/Android Studio,用 Expo Go/Snack 即可立即测试
  • 借助 CNG(`expo prebuild`)可以重新生成 native 文件夹——“eject”不再是单向的门
  • config plugin 体系以可编程、可重复的方式配置 native 项目
  • EAS Update 提供独立于 native 层、即时生效的 OTA JS 更新
  • EAS Build 免费计划每月包含 15+15 次构建和 1,000 MAU 的更新——小型项目零成本起步
  • EAS Workflows 支持由 GitHub 事件/cron 触发,从 app config 自动生成 native 构建
  • 版本升级简单到只需更新 npm 依赖再执行 `prebuild --clean`
  • 作为 React Foundation 的创始成员,与 RN 生态保持紧密同步

缺点

  • Expo SDK 始终落后 RN 核心一个版本(SDK 57 → RN 0.86,而非 RN 0.87)——无法立即用上最新的 RN 特性
  • 自 2026 年 9 月 3 日起,Expo Go(iOS)在终端和 App 内都需要登录
  • 为极少数/特殊的 native SDK 编写 config plugin 可能需要额外的工作量
  • 超出 EAS 免费额度后需升级到付费的 Starter(19 美元/月)或 Production(199 美元/月)
  • EAS 以云端优先设计,与企业级 on-prem CI 的强制要求兼容性较弱
  • 直接手动修改 native 文件夹后再运行 prebuild,会悄悄清除这些改动(除非已迁移到 config plugin)

最适合

希望快速启动新 React Native 项目的团队能够使用 EAS 云端 CI/CD 的中小规模项目MVP/原型开发与快速迭代对 OTA 更新需求高、希望不等待商店审核就发布 JS 修复的应用native 需求可以通过标准 config plugin 生态(相机、通知、定位等)满足的项目

Bare React Native

优点

  • 直接且无限制地访问 native 项目(Xcode/Gradle)——没有任何抽象层
  • RN 的每一个次要版本(0.85、0.86、0.87……)都能立即获取,无需等待 Expo SDK 周期
  • 完全不依赖 EAS——可以搭建任意你想要的 CI/CD 服务或 on-prem pipeline
  • 不局限于 config plugin 生态,可以直接集成任何 native SDK
  • 126,507 个 GitHub star 和 25,238 次 fork,社区庞大且成熟
  • MIT 许可、开源,没有 vendor 依赖

缺点

  • 搭建需要 Xcode + CocoaPods、Android Studio + SDK + Gradle——首次搭建明显比 Expo 更耗时
  • native 的 `ios`/`android` 文件夹长期存在;每次版本升级都需要借助 Upgrade Helper 手动应用 diff
  • 没有现成的 OTA 更新方案——需要手动集成 `expo-updates` 或搭建替代方案
  • 即使想使用 CI/CD(包括 EAS),也需要手动同步 native 构建凭证
  • native 包的额外配置(Info.plist 权限、Manifest 条目、Gradle 设置)需要手动完成——不具备 config plugin 的可重复性
  • 对新加入的开发者而言,工具链搭建会明显拉长首次构建所需的时间

最适合

需要 EAS 不支持的特殊工具链或构建环境的项目有企业级 on-prem/自托管 CI 强制要求的团队需要集成 config plugin 无法覆盖的、极其罕见或特殊 native SDK 的应用需要持续深度介入 native 代码的大型复杂应用希望不等待 SDK 周期、直接使用 RN 核心最新版本的团队

代码对比

Expo
// Expo — 通过 app.config.ts + 本地 config plugin 添加 native 权限(TypeScript)

// plugins/withCameraUsage.ts — 向 Info.plist 添加相机权限的 config plugin
import { ConfigPlugin, withInfoPlist } from "expo/config-plugins";

const withCameraUsage: ConfigPlugin = (config) =>
  withInfoPlist(config, (config) => {
    config.modResults.NSCameraUsageDescription =
      "Profil fotoğrafı çekmek için kameraya erişim gerekiyor";
    return config;
  });

export default withCameraUsage;

// app.config.ts — 通过文件路径引用该 plugin(需要 npm i -D tsx)
import "tsx/cjs";
import { ExpoConfig, ConfigContext } from "expo/config";

export default ({ config }: ConfigContext): ExpoConfig => ({
  ...config,
  name: "MyApp",
  slug: "my-app",
  version: "1.0.0",
  plugins: [["./plugins/withCameraUsage.ts"], "expo-router", "expo-updates"],
  updates: { url: "https://u.expo.dev/your-project-id" },
  runtimeVersion: { policy: "appVersion" },
});

// 终端:生成并应用 native 文件夹(CNG)
// npx expo prebuild --clean

// 运行 EAS Build 并发布 OTA 更新
// eas build --platform all --profile production
// eas update --branch production --message "Bug fix: login crash"
Bare React Native
// Bare React Native — 安装依赖包 + 手动 native 配置(TypeScript)

// 1) 安装依赖包:autolinking 自动关联,拉取 pod,重新构建
// $ npm install react-native-vision-camera react-native-nitro-modules react-native-nitro-image
// $ npx pod-install
// $ npm run ios     # Android: npm run android

// 2) 手动添加权限 — 这一步不包含在 autolinking 中
// ios/MyApp/Info.plist:
// <key>NSCameraUsageDescription</key>
// <string>Profil fotoğrafı çekmek için kameraya erişim gerekiyor</string>
// android/app/src/main/AndroidManifest.xml:
// <uses-permission android:name="android.permission.CAMERA" />

// 3) JS 端用法(共享代码)
import React, { useEffect } from "react";
import { Camera, useCameraPermission } from "react-native-vision-camera";

function ProfileCamera() {
  const { hasPermission, requestPermission } = useCameraPermission();

  useEffect(() => {
    if (!hasPermission) requestPermission();
  }, [hasPermission, requestPermission]);

  return <Camera style={{ flex: 1 }} isActive={true} device="back" />;
}

export default ProfileCamera;

// 4) 版本升级(0.86 -> 0.87):没有对应的 CLI 命令
// Upgrade Helper(网页工具):https://react-native-community.github.io/upgrade-helper/
// -> 手动在 Podfile.lock、build.gradle、AppDelegate.swift 上应用 diff

// 5) 你自己的 CI pipeline(GitHub Actions,摘要)
// - run: npx pod-install
// - run: xcodebuild -workspace ios/MyApp.xcworkspace -scheme MyApp -configuration Release

结论

2026 年的默认答案是 Expo + CNG:由于 `expo prebuild` 可以重新生成 native 文件夹,“eject”不再是单向的门;config plugin 体系能覆盖大部分 native 配置需求,EAS Build 的免费层级也足以满足中小型项目。选择 Bare React Native 的理由虽然范围较窄但确实存在:EAS 不支持的特殊工具链、必须使用 on-prem CI,或是极其罕见的 native SDK。如果这三者都不成立,就从 Expo 开始。

获取免费咨询
常见问题

常见问题

2026 年的默认答案是 Expo + CNG:config plugin 体系能覆盖大多数 native 模块,EAS Build 的免费层级(每月 15+15 次构建)足以满足中小型项目,而且有了 `expo prebuild`,深入 native 代码不再是不可逆的决定。真正能让 bare RN 站得住脚的理由是:EAS 不支持的特殊工具链、企业级 on-prem CI 的强制要求,或是 config plugin 无法覆盖的极罕见 native SDK。

相关博客文章

查看全部文章

相关项目

查看全部项目
全部对比