React Native 0.76 新架构到底要不要开?我拿 Pixel 4a 和 iPhone SE 2 跑了 7 天,踩完这些坑再决定

🔑 关键词:React Native新架构, Expo SDK 52, Hermes, FlatList性能优化, TurboModules

📖 摘要:不是官方文档复述。我用一个 120 项商品列表的 Expo SDK 52 + RN 0.76 项目,在 Pixel 4a 和 iPhone SE 2 上对比新旧架构、Hermes、FlatList 参数和回滚步骤,给出一套先量化再升级的排查流程。

先说结论,不一定对,但我自己项目里是这样:React Native 0.76 之后新架构默认打开,真正明显的变化不是“所有页面都丝滑”,而是原生模块调用方式从 bridge 换成了 JSI/TurboModules,Fabric 接管渲染。 你要是指望开个 newArchEnabled=true 就把 FlatList 掉帧治好,大概率会骂人。 我这次拿一个 Expo SDK 52 项目试了 7 天,RN 0.76.5,React 18.3.1,Hermes 默认,Reanimated 3.16.1,react-native-screens 4.4.0,gesture-handler 2.20.2。 测试机不是旗舰:Pixel 4a Android 13、iPhone SE 2 iOS 18.1,都是 release 包,不是 dev menu 里瞎滑。 商品列表 120 项,每项一张 300x300 CDN 图,带价格、标签、倒计时。先别急着升,后面我把启动、滚动、回滚、库兼容都拆开说。

图片

我怎么判断自己有没有开新架构

第一步不是改配置,是先确认现在到底跑的是什么。 Bare RN 在 android/gradle.properties 看 newArchEnabled,0.76 默认是 true;iOS 看 Podfile 里的 :hermes_enabled 和 :new_arch_enabled,但别只看文件,跑起来用代码验。 我在 App.tsx 里临时打了三行:console.log(global.RN$Bridgeless)、console.log(!!global.nativeFabricUIManager)、console.log(global.__turboModuleProxy ? 'turbo' : 'no turbo')。 Pixel 4a 上 bridgeless 为 true、Fabric 存在、turbo 存在,才算新架构链路通了。 Expo 项目用 npx expo config --type introspect | grep -i newArch,SDK 52 里能看到 newArchEnabled: true。 如果你用的是 SDK 53,RN 0.79,新架构更默认,回退空间更小。 这里有个小坑:npx react-native info 的输出里有时不直接写 New Architecture,别拿它当唯一证据。确认完再谈性能,不然你测的是空气。

图片

启动时间:新架构不是免费午餐

图片

我测冷启动用 adb shell am start -W -n com.xxx/.MainActivity,清后台,每轮 10 次取中位数。 Pixel 4a 上旧架构 2.03s,新架构 2.41s;首次安装后第一次启动新架构能到 3.8s,因为 TurboModules 和 Fabric 有懒加载初始化。 iPhone SE 2 上差距小:旧 1.31s,新 1.39s,基本在误差里。 这里别急着下结论说新架构慢,第二次以后启动新架构会追回来,Pixel 4a 稳定后是 2.11s 对 2.03s,还是略慢 80ms 左右。 我项目里启动阶段做了 3 件事:把 react-native-mmkv 初始化从 App 函数体挪到 useEffect 后;把 Sentry 的 enableAutoSessionTracking 延后 500ms;把 expo-updates 的 checkAutomatically 改成 ON_LOAD 而不是 ON_ERROR_RECOVERY。 改完新架构 Pixel 4a 中位数到 1.92s,旧架构 1.88s。所以启动这块,新架构不是开关,是你要不要接受那几十到几百毫秒的初始化成本。

列表滚动:Fabric 有收益,但先查 JS 层

图片

这是我最想说的:列表卡顿 80% 不在桥,也不在 Fabric,在你自己 renderItem 里。 我旧代码每个 item 里 new Intl.NumberFormat('zh-CN', { style: 'currency', currency: 'CNY' }).format(price),120 项滚动时 JS 线程疯狂分配。 改成模块顶层建一个 formatter,再给 item 加 React.memo,FlatList 参数调成 initialNumToRender={8}、maxToRenderPerBatch={6}、windowSize={7}、updateCellsBatchingPeriod={50}、removeClippedSubviews={Platform.OS === 'android'}、getItemLayout 写死行高 132。 Pixel 4a release 包,旧架构平均 42fps 提到 51fps;开新架构再跑到 55fps。注意这是 Pixel 4a,低端安卓,Fabric 的同步布局和更少的序列化开销有帮助。 iPhone SE 2 旧架构已经 59fps,新架构也是 59fps,肉眼看不出。 图片我从 Image 换到 expo-image,加 cachePolicy='memory-disk'、recyclingKey={item.id}、contentFit='cover'、transition={120},Android 低端机丢帧又少了大概 4 帧。 别迷信新架构,先把 memo、formatter、图片缓存、keyExtractor 做完。

库兼容和回滚:别在周五下午升级

图片

新架构最烦的是库。 我的项目里 react-native-reanimated 升到 3.16.1、react-native-gesture-handler 升到 2.20.2、react-native-screens 升到 4.4.0、react-native-safe-area-context 升到 4.12.0 才稳。 react-native-mmkv 必须 v3 以上,v2 在新架构下直接崩,报的是 JSI 相关错误。 react-native-fast-image 我劝你先别用,维护状态一般,换 expo-image 省心。 回滚步骤记一下:Bare RN 0.76 在 android/gradle.properties 设 newArchEnabled=false,iOS 在 Podfile 设 :new_arch_enabled => false,然后 cd android && ./gradlew clean,cd ios && rm -rf Pods build && pod install。 Expo SDK 52 在 app.json 里写 expo.newArchEnabled=false,再 npx expo prebuild --clean。 但注意 --clean 会把你手改的 android/ios 文件冲掉,原生配置要提前塞进 expo-build-properties 或 config plugin。 我那次手改过 android/app/build.gradle 的 minSdkVersion 24、compileSdkVersion 35、targetSdkVersion 35,prebuild 后全没了,又花半小时补。 所以小团队没三个以上原生模块要维护,我反而觉得 Expo CNG + config plugin 比裸 RN 更省命;有重度原生 SDK,再考虑 bare。

图片

我的独立结论:先量化,再决定

如果你问我 2025 年新项目还上不上新架构,我会说:上,但别把它当性能优化项目。 RN 0.76 的新架构已经是默认路线,库生态到 2025 年初基本跟上,继续留在旧架构的维护成本会越来越高。 可如果你现在的痛点是启动慢、列表卡、包大,升级前先做三张表:冷启动中位数、列表 fps、原生模块调用次数。 我的项目里原生模块调用只有 MMKV 和安全区,开新架构收益主要在低端 Android 列表,启动还略慢;另一个同事的项目有 12 个原生 SDK,新架构后 bridge 序列化没了,相机回调延迟从 90ms 降到 35ms 左右,那才叫质变。 判断标准很简单:你的瓶颈如果发生在 JS 单线程里,先改代码;你的瓶颈如果发生在 JS 和原生频繁通信,新架构值得。 别在周五下午升级,别一次改 RN、Expo、Reanimated、导航四样,分开提交,留好回滚分支。 最后一句不是金句,是我踩坑后的实话:新架构不是银弹,它只是把旧桥拆了,路还得你自己铺。

🏷️ 标签: