Flutter vs React Native
全方位对比Google基于Dart的Flutter与Meta基于JavaScript/TypeScript的React Native。2025年哪个跨平台框架更胜一筹?
借助 Node.js LTS 即可搭建、通过 CNG 实现可逆的 managed React Native 框架
在 native 工具链上拥有完全控制权的核心 React Native 搭建方式
2026 年的默认答案是 Expo + CNG:由于 `expo prebuild` 可以重新生成 native 文件夹,“eject”不再是单向的门;config plugin 体系能覆盖大部分 native 配置需求,EAS Build 的免费层级也足以满足中小型项目。选择 Bare React Native 的理由虽然范围较窄但确实存在:EAS 不支持的特殊工具链、必须使用 on-prem CI,或是极其罕见的 native SDK。如果这三者都不成立,就从 Expo 开始。
| 分类 | Expo | Bare 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 — 通过 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 — 安装依赖包 + 手动 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 Release2026 年的默认答案是 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。