围绕 DartNative 的讨论很容易被一句社交媒体嘲讽带偏:React Native 需要 Nitro 这种“火箭”,DartNative 不需要。这个说法有传播性,但对技术选型帮助不大。真正值得讨论的不是谁骂得更狠,而是 DartNative 试图下注的架构是否成立:用 Dart 写应用逻辑,用 Dart AOT 产出原生机器码,让 Dart 运行在平台主线程上,通过 iOS 的 FFI、Android 的 FFI 到 JNI 同步驱动 UIKit 和 Android View;布局交给 Yoga;常规界面不经过自绘引擎,只有在确实需要画布和 shader 时才可选接入 Skia。
这条路线既不像 Flutter,也不是旧 React Native 的简单复刻。Flutter 的核心选择是统一渲染:应用的大部分界面由 Flutter widget 树、layout、paint、compositing 和 Impeller/Skia 体系掌控,换来高度一致的跨平台表现、成熟工具链和庞大生态,代价是很多平台控件与交互都不是系统原生控件本身。React Native 的核心选择是保留宿主平台视图:React 负责声明式更新,最终挂载到 UIView、TextView、ScrollView 等 host views 上。DartNative 则试图同时要两件事:Flutter 风格的 Dart/Widget 开发体验,以及更接近 React Native 的真实原生视图,但把 JavaScript 运行时与跨线程同步这层拿掉。
先把 DartNative 的实际结构讲清楚
DartNative 的公开架构可以拆成几层:上层是开发者写的 Dart widget 与状态更新;中间有 reconciler,对前后两次 widget tree 做 diff,把变化转成对原生视图的创建、属性更新、插入、删除;再下面是 platform bindings,iOS 通过 Dart FFI 直接调用本地实现,Android 通过 FFI 再进入 JNI;最终落到 UIKit 或 Android View 系统。布局使用 Meta 的 Yoga,也就是 React Native 长期使用的 Flexbox layout engine。官方文档强调这些层在平台主线程同一条调用栈里完成,setState、diff、原生视图更新、layout 与 frame commit 不需要传统 bridge 队列或线程跳转。
这里的“真实原生视图”是关键。Text 对应 UILabel/TextView,输入框对应 UITextField/EditText,滚动和列表可以落到 UIScrollView、UITableView、RecyclerView、UICollectionView 等平台组件。这和 Flutter 的“把控件画出来”不是同一类抽象。真实原生视图的好处很直观:文本输入、键盘、系统导航、辅助功能、滚动惯性、平台外观更新等行为天然更接近系统。坏处也同样真实:跨平台一致性不再主要靠一个统一渲染引擎保证,而要在 iOS 与 Android 两套宿主系统上做大量绑定、适配、bug 修复和语义对齐。
Dart AOT 的作用也要说准确。它不是魔法加速器,而是把 Dart 代码提前编译为原生机器码,避免生产环境依赖 JIT 暖机。和 React Native 常用的 Hermes 相比,差异不是简单的“AOT 对 JIT”,因为 Hermes 本身也以提前生成字节码、启动快、无 JIT 为目标;更准确的差异是:DartNative 执行的是 Dart AOT 机器码,而 Hermes 执行 JavaScript 字节码,并且 React 的 render、layout、commit 到 UI mount 仍存在运行时与线程模型边界。这个边界已经比旧桥架构小得多,但并没有消失。
与现代 React Native 公平比较:旧 bridge 不是今天的靶子
任何认真比较都不能拿十年前的 React Native 当靶子。React Native New Architecture 已经把老的异步序列化 bridge 替换成 JSI、Fabric 和 TurboModules 这套新基础。JSI 让 JavaScript 与 C++ 宿主对象可以更直接地交互;Fabric 重新设计渲染管线,引入 C++ shadow tree、同步/异步 commit、host view mounting;TurboModules 通过代码生成和懒加载改善原生模块调用。再加上 Hermes、Reanimated worklets、react-native-screens、react-native-keyboard-controller 以及 Nitro Modules 这类社区方案,今天的 RN 性能瓶颈已经不是“所有东西都过 JSON bridge”这么粗糙。
Nitro 值得被公平对待。它代表的是 RN 社区继续降低 JS 与 Native 模块边界成本的努力:用 JSI、C++、代码生成和类型化接口减少传统 Native Module 的胶水层。对于相机、图像处理、加密、数据库、音视频、蓝牙等重 native work 的场景,Nitro 这类方向不是笑话,而是实际工程需求。DartNative 的嘲讽可以当营销看,但技术上不能因此否定 Nitro。问题只在于:Nitro 优化的是边界,而 DartNative 的架构赌注是让应用 UI 逻辑一开始就站在主线程与原生视图旁边,尽量减少这条边界。
因此 DartNative 与现代 RN 的真实分歧是线程与树模型。React Native 依然是 React 生态:JS/Hermes 运行时负责应用逻辑和 React reconciliation,Fabric 管理 shadow tree 与 mount,UI thread 才是最终能操作 host views 的地方。这个模型的优点是生态、React 编程模型、Web/RN 心智迁移和平台扩展性;代价是交互非常密集、键盘/手势/高刷动画/长列表等场景下,开发者需要非常清楚哪些工作在 JS thread,哪些在 UI thread,哪些交给 worklet 或 native module。DartNative 的模型更短:Dart 回调、状态更新、diff、Yoga layout、native view mutation 尽量都在主线程同步发生。它减少了协调成本,但也把主线程负载管理变成框架和应用共同承担的问题。
与 Flutter 比较:它反对的不是 Dart,而是自绘栈
DartNative 与 Flutter 的关系更微妙,因为它借用了 Dart、Flutter 工具链和 Flutter 风格 API 心智,却反对 Flutter 最核心的渲染路线。Flutter 的优点非常强:一致的 widget 体系、成熟的 DevTools、热重载、Material/Cupertino 组件、优秀的布局与动画模型,以及大量可复用包。它适合需要像素一致、设计系统统一、跨端扩展明确的团队。很多产品并不需要每个按钮都是系统原生按钮,只需要稳定、高效、可控地交付。
DartNative 提出的反命题是:在高级消费应用、强输入、强列表、强平台质感的移动场景里,系统控件本身有不可替代的价值。键盘贴合、输入法边界、iOS 返回手势、系统导航栏、文本选择、辅助功能、深浅色切换、滚动与惯性,这些细节用自绘栈也能做,但往往需要追赶平台行为。DartNative 希望把这些行为交还给 UIKit 与 Android View,把 Dart 变成驱动原生 UI 的语言,而不是驱动自绘引擎的语言。
但反过来说,Flutter 的自绘路线也不是“错误”。统一渲染让 Flutter 能在移动、桌面、Web、嵌入式之间保持相对一致的模型;复杂自定义 UI、品牌化组件、图形密集界面、强设计一致性场景,Flutter 的确定性可能反而是优势。DartNative 可选 Skia 的存在也说明:一旦进入 shader、粒子、复杂 canvas、像素级一致输出,它同样需要专门的 GPU 画布能力。区别在于 DartNative 把 Skia 放在可选层:常规 UI 尽量用系统 view,只有画布型需求才接入 dartnative_skia。官方文档也明确提醒 Skia 不免费,会增加体积并产生额外 GPU 工作。
Yoga 与 reconciler:性能卖点背后的真正工程量
Yoga 是 DartNative 与 React Native 的共同点,不是 DartNative 独占优势。它把 Flexbox 布局建模成树遍历,适合 Column、Row、Flex、Padding、Align 这类声明式布局。DartNative 的优势主张不在“我有 Yoga,你没有”,而在“Yoga layout 和 native mount 不跨 JS/UI 线程边界”。这在理论上确实能减少调度成本,尤其是触摸回调、键盘变化、局部 setState、列表插入等需要快速更新视图树的场景。
但同一主线程同步执行也有另一面。如果 Dart 侧 build/diff 逻辑太重、同步计算太多、状态更新粒度粗,主线程仍然会被阻塞。传统 RN 至少把大量 JS 工作放在 JS thread,虽然带来同步问题,但也把一部分计算从 UI thread 分离出去;Flutter 也有自己明确的 frame pipeline 与 isolate 模型。DartNative 的“同线程”不是免费午餐,它要求 reconciler 足够小心,应用代码不能在交互路径上做重计算,框架需要有清晰的批处理、dirty 标记、列表复用、图片解码与 native 侧缓存策略。否则“没有线程跳转”会变成“所有错误都直接堵在主线程”。
这也是为什么不能把 DartNative 的架构解读成“必然普遍更快”。它的确在若干结构性问题上少了一层:没有 JS bridge,没有自绘引擎重画整套控件,没有常规 UI 的 Skia 依赖,没有 JS thread 到 UI thread 的固定协调路径。可是应用性能从来不是由单一边界决定。冷启动、首屏、列表滚动、键盘动画、图片解码、复杂文本、内存峰值、插件调用、低端机、Android 厂商差异、iOS 新版本 API 变动,每一项都可能改变结论。架构可以给出合理预期,不能替代真实测量。
成熟度与许可边界比口号更重要
目前 DartNative 还处在非常早的公共阶段。公开仓库主要承载文档、playground、tutorials、plugin examples、issue tracker 与发布说明;框架实现本身在私有仓库。官方 changelog 在 2026 年 9 月连续发布 preview 修复,内容涉及系统外观、键盘 action、Android input bar、DefaultTextStyle、RTL、TextField formatter、iOS 26 导航栏和搜索栏等。这说明项目在快速修问题,也说明 API 与实现仍处于预览期,平台细节正在被真实使用反馈不断补齐。
许可边界同样不能忽略。DartNative 不是一个传统意义上的完全开源框架:构建和发布自己的应用需要有效订阅与 license token;公开 demo、playground、tutorial 和插件示例可以免费运行;已经在有效订阅下分发给终端用户的应用,在订阅到期后继续运行,但到期会停止新的构建与发布权利。License 里还有 sunset commitment:在满足停止维护条件后,承诺在一定时间内以 BSD 3-Clause 形式发布当时源码及 first-party plugins,但这个承诺的触发、范围和法律执行仍然是商业许可框架的一部分。对个人试验这可能不是问题;对公司选型,这就是采购、合规、供应链和退出策略问题。
私有实现还会影响技术尽调。RN 和 Flutter 的核心实现、issue 历史、PR 讨论、生态包兼容路径都长期公开,团队可以直接读源码、定位问题、临时 fork、等待上游或自行打补丁。DartNative 当前更像商业 SDK:你可以通过文档、demo、发布节奏、问题响应和实际试用判断质量,但不能用同样方式审计全部实现。这个边界不一定意味着不能用,却意味着采用前必须把 vendor risk 写进评估表。
实用评估计划:别吵,拿同一组屏幕测
如果团队真的想判断 DartNative 是否适合自己,最好的办法不是引用社交媒体,也不是转述官方 benchmark,而是做一个小而硬的对照项目。选三到五个最代表业务风险的屏幕:一个长列表或聊天流,一个复杂输入表单,一个带系统导航/返回手势/键盘联动的页面,一个图片密集 feed,一个需要原生模块的功能。分别用当前团队熟悉的 Flutter 或 React Native 实现基线,再用 DartNative 复刻到足够接近生产质量。
测量指标要提前写死。性能方面至少看冷启动到首帧、首个可交互时间、滚动丢帧、键盘弹出/跟手、列表快速插入、内存峰值、图片缓存命中、低端 Android 表现和 120Hz iPhone 表现。工程方面看开发速度、热重载/热重启体验、崩溃定位、日志、IDE 支持、CI 构建、包体大小、插件覆盖、系统权限接入、升级成本、团队学习成本。产品方面看系统质感、辅助功能、深色模式、动态字体、RTL、输入法和地区化边界。所有测试都应在真实设备 release/profile 构建上完成,不能只看模拟器 debug。
评估 RN 时也要给现代方案完整机会:开启 New Architecture,用 Hermes,使用 Fabric 兼容组件;原生模块路径比较 TurboModules、Nitro Modules 或成熟现有库;键盘与动画不要只用 stock RN,而应纳入 Reanimated worklets、react-native-keyboard-controller、react-native-screens 等今天团队实际会采用的组合。评估 Flutter 时也不要停在默认 demo,应使用当前 Impeller、真实 release 构建、合理图片缓存包、平台通道和必要原生插件。只有这样,DartNative 赢了才说明它赢的是现代对手,而不是旧印象。
最终决策可以按三档处理。第一档是探索:做 playground、demo 和内部工具,观察文档、SDK 更新和问题响应,不承担核心业务风险。第二档是局部试点:选择平台质感非常重要但业务闭环相对独立的页面或新产品,建立回滚与并行实现方案。第三档才是主框架迁移:只有当插件、稳定性、许可、CI、招聘、调试、性能数据都过关时再考虑。对于已经有成熟 RN/Flutter 资产的团队,DartNative 更合理的初始定位不是“立刻替换”,而是“验证一条可能更贴近原生 UI 的路线”。
结论:这是架构赌注,不是胜利宣言
DartNative 最有价值的地方,是把跨端讨论重新拉回一个本质问题:我们到底要统一渲染,还是要保留系统 UI?要把性能问题交给更好的桥和模块系统优化,还是从线程与视图模型上减少边界?它的答案很激进:Dart AOT、主线程同步、FFI/JNI、真实原生视图、Yoga 布局、可选 Skia。这个答案在技术上有清晰逻辑,也确实击中了 Flutter 和 React Native 各自的一些长期争议。
但清晰逻辑不等于普遍胜利。React Native New Architecture、JSI、Fabric、TurboModules、Nitro 代表的是庞大生态在持续缩短边界;Flutter 代表的是统一渲染和成熟工具链的工程确定性。DartNative 现在证明的是一种值得严肃测试的架构假设:如果把 Dart 直接放到原生 UI 主线程旁边,能不能在保持 Flutter 式开发体验的同时拿到更自然的平台质感。它还没有证明自己在所有应用、所有平台、所有团队里都更快、更稳、更便宜。
所以,最冷静的判断是:不要被粗口营销牵着走,也不要因为项目年轻就一票否决。DartNative 值得技术负责人拉出来做一次严格 POC,尤其是那些对键盘、列表、导航和平台质感极其敏感的移动产品。但在没有独立 benchmark、长期维护记录和完整生态验证之前,把它称作“React Native 终结者”或“Flutter 替代品”都太早。它是一场架构押注,押对了会改变一部分高质感跨端应用的选择;押错了,也会再次提醒我们:跨端框架的难点从来不是写出漂亮路线图,而是在多年平台细节里活下来。