Expo 的 Exact 是什么:为 AI 代理设计的 Rust 应用框架,想解决什么问题

深度解析2026-11-12发布 WarpEdit
1 0 0

Exact 是 Expo 联合创始人 Charlie Cheever 在 2026 年 11 月 9 日公开预览的一个新应用框架,核心用 Rust 写成,主打「Agent Native」:默认大部分代码会由 AI 代理来写,所以框架从语言、测试到调试工具都按代理的需要来设计。界面用一门新语言 Contract 描述,业务逻辑用 TypeScript 或 Rust,同一份代码可以跑在网页、macOS、iOS 和 Linux 上,Android 和 Windows 还在早期。它想解决两个问题:一是让代理能自己构建、运行、查看和测试应用,不用人一直盯着;二是在跨平台的同时拿到接近原生的性能。需要先说清楚:Exact 目前是 pre-alpha 预览版,作者自己说有些东西「肯定没做完或者是坏的」;文中所有性能数字都来自作者和仓库的自测,不是第三方评测。

Exact 应用框架封面,同一块透明板投出网页、桌面窗口和手机的轮廓

Exact 是怎么工作的

用 Exact 写应用,分成两部分:

  • 界面和状态写在 .contract 文件里,包括页面长什么样、有哪些状态、用户操作会改变什么。
  • 数据和业务逻辑写在 TypeScript 或 Rust 里,比如请求接口、读写数据库。两者之间只有一个「数据接口」,逻辑层返回的数据会按 Contract 里声明的结构检查。

Contract 编译器把界面编译成一份紧凑的「plan」(可以理解为描述界面和状态变化的数据表加字节码)。之后在不同平台上执行方式不同:

  • 网页:plan 变成一个 ES 模块,配一个约 20 KB 的运行时,直接操作浏览器真实的 DOM 和 CSS。
  • macOS、iOS、Linux:由 Rust 写的运行器执行同一份 plan,用 Rust 布局引擎 Taffy 按 CSS 规则算出每个元素的位置,再交给各平台自己画:Mac 用 AppKit,iPhone 用 UIKit,Linux 用 GPU 或 CPU 绘制。

README 特别强调三点:没有 WebView,界面层没有 JavaScript 桥,第一帧画出来之前不执行任何应用 JavaScript。在原生平台上,TypeScript 在构建时编译成 Hermes 字节码,首帧之后才加载;网页上的业务逻辑则由浏览器执行。

这和 React Native / Expo 的路线明显不同。React Native 是用 React 写界面,JavaScript 在运行时驱动原生组件;Exact 的 README 写明「没有 JSX 或 React 这一层」,界面完全由 Contract 声明。

app.contract 经 Contract 编译器生成 plan,再由网页或 Rust 运行器执行;TypeScript 或 Rust 数据源独立提供数据
据 Exact README 的架构图重绘。实线表示界面的编译和执行路径,虚线表示数据源向运行时提供经校验的数据。

「为代理设计」具体指什么

「Agent Native」听起来像营销词,但 Exact 有几项很具体的设计。

十个统一操作。代理通过一个脚本 scripts/agent.mjs 操控应用,只有十个操作:tree · screenshot · tap · type · state · layout · logs · clock · prefer · perf,在网页、Mac、iPhone(模拟器或真机)和 Linux 上用法完全一样。README 说之所以刻意只留十个,是因为上一代版本的代理接口「一次加一个合理的功能」,最后涨到了八十个。

时钟归代理控制。这是最有意思的一点。平时让代理测试动画,它只能「等一会儿再截图」,等短了动画没播完,等长了浪费时间,结果还时好时坏。在 Exact 里,两次操作之间界面完全静止,代理可以直接说「时间快进 60 秒」(clock +60000)或「等所有动画结束」(clock settle),然后读结果。作者的说法是,这能减少代理排查问题时要考虑的可能性。

测试就是操作脚本。app.test.contract 文件就是一串上面那些操作加断言,不用改就能在任何平台跑。

编译器教代理写代码。按作者的说法,Contract 很新,不能指望代理一开始就熟悉它的语法。作者的思路不是让代理先读一大本手册,而是让编译器报错时把正确写法告诉它。README 给的例子是,写了 size 属性时,编译器会提示「这里要用网页的写法 font-size」。一次编译最多报二十个独立错误,还能输出 JSON 供工具读取。作者认为,有针对性的错误信息是让代理「只读它需要的文档」的最便宜的办法之一。

整个应用能塞进上下文。README 写道,Contract 故意做得很小,一个完整应用能放进一个上下文窗口;每次写入都要声明,每个列表都要有 key,每个值都有类型。

Contract 为什么故意受限

Contract 的写法像 Python:靠缩进表达层级,格式要求严,写得很简洁。但它又像 Rust 一样强类型、要求显式声明。很多在 JavaScript 框架里很常见的东西,Contract 直接不让写:

  • 界面里不能写 JavaScript,表达式不能有副作用,也不能做 I/O。
  • 动作里不能写循环,不能 await,函数不能递归。
  • 没有 React 那种 useEffect。
  • 状态只能在「action」里改,数据只能通过「数据源」进出。

作者给的理由是:这些限制让编译器能完整分析整个应用。编译时就知道数据怎么排布、彼此怎么关联,所以更新时可以精确地只改需要改的地方,不需要虚拟 DOM、重新渲染或单独的 hydration(网页先显示静态内容、再挂上交互的过程)。也因为能完整分析,构建时可以把首屏界面和能提前算好的数据直接「烤」进应用里,相当于原生版的静态生成 HTML。README 的说法更直接:代理写不出数据竞争,是因为它根本写不了能引发数据竞争的代码。

需要接触平台原生能力时,Exact 提供两种方式:一是「原生模块」,用 Swift、Kotlin 或 Rust 实现一个平台控件,在 Contract 里当一个带连字符的标签用(例如 exact-map);二是作者称为「Access Hatch」的机制,可以拿到框架自己创建的原生对象(比如一个 UIView),给它补属性或回调。作者举的例子是,Apple 官方的 Liquid Glass 示例应用里,长按卡片会出现裁切和闪白,而在 Exact 里可以逐个控制原生元素来修正。

性能数字要怎么看

作者的文章和 README 给了不少性能对比。先强调一遍:下表列的是作者或项目仓库公布的数据,本文未独立复现这些对比。

场景 作者给出的结果 来源
网页:Nolan Lawson 提出的 Pokédex 基准 与 Astro 不相上下,明显领先 Next.js 和 SvelteKit 作者文章
网页:让 AI 写同一个应用 比 Next.js 更快写出正确结果,成本相近;Astro 静态站仍更便宜更快 作者文章
网页:RealWorld(Conduit)基准 Exact 运行时比 React SSR 完成 hydration 早约 300 毫秒;代码 26 KB 对 React 的 81 KB README
iOS:同一内容流的滚动 Exact 稳定 120fps、零掉帧;SwiftUI 掉到 30–50fps;略胜常规 UIKit 写法 作者文章
iOS:启动速度 与 Shopify 优化后的原生 Shop 应用对比,调用同一个 GraphQL 接口,Exact 启动更快 作者文章
开发:保存改动到生效 Contract 改动 10–20 毫秒、TypeScript 通常不到 100 毫秒;README 测得新应用一次改动 99 毫秒 作者文章、README

另外,README 里的「冷启动到可交互首帧 100 毫秒(p50)」「改动到呈现 100 毫秒(p50)」是项目给自己定的性能预算目标,每次提交都会跟踪,不等于在所有设备上实测都能达到。

看这些数字时可以注意三点。第一,作者自己也承认,Shopify 花时间也能把 Swift 版做到一样快,UIKit 下足功夫也能达到同样帧率,Exact 的卖点是「开箱即得」。第二,基准测试的应用规模、设备和网络条件,在文章里没有完整公开。第三,Astro、Next.js 这些框架的作者没有参与这些对比。因此,表里的差距只适用于作者展示的应用和测试条件。打算迁移现有应用时,更值得比较的是自己的首屏、列表和数据请求。

Pokédex 首页的 Lighthouse 移动端基准表,Exact 的 LCP 为 802 毫秒,Astro 为 805 毫秒
作者自测数据。每个框架取 5 个代理构建的 Pokédex 应用,图中为移动端 Lighthouse 测试的中位数。此页最大内容绘制(LCP)为 Exact 802 毫秒、Astro 805 毫秒。

平台支持和成熟度

作者在文章里给的成熟度排序是:iOS 最成熟,网页和 macOS 都「相当不错」,Android、Windows 和 Linux 能用但不够成熟。README 的口径稍有不同:它把网页、macOS、iOS 和 Linux 列为四个已经可用的平台,v1 的目标是让一个真实应用(示例里的 Caltrain 列车时刻应用)用同一份 Contract 在这四个平台上跑起来;Windows 和 Android 列在「还没做完」里,Android 能构建、能在模拟器和手机上跑测试,但分发和应用商店打包还不存在。

除了平台,还有几个「pre-alpha」的具体含义,都写在 README 里:

  • 没有 API 稳定性,没有向后兼容,没有迁移指南,而且是有意为之。代码每天都在变。
  • 没有打包好的命令行工具,要从源码仓库里用;exact new 创建的应用通过路径引用你本地的仓库。截至 2026 年 11 月 12 日,仓库也没有发布任何 Release。
  • 作者文章提到改动可以通过 OTA(空中更新)下发,但 README 写明,目前签名分发只覆盖 plan 和资源文件,TypeScript 和 Rust 模块的线上更新还没实现,应用商店规则本身也有限制。
  • 设计决策记录在一个非公开仓库里,README 和文档用编号引用(例如「LLP 1115」),外部读者看不到原文。

还有一个和隐私有关的细节:Exact 鼓励代理把开发中遇到的问题写成「日记」反馈给 Expo。按 README,记录内容包括提交号、命令、退出码、耗时和系统,不包括命令输出和应用代码;默认是每次先展示要发送的内容、问过你再发,可以用 EXACT_FEEDBACK=0 全局关掉。

和 Expo、React Native 的关系

很多人第一反应是:Expo 要放弃 React Native 了吗?作者在文章里明确说不会。Expo 框架不会消失,公司会继续支持,而且「增长得比以往都快」,AI 也在推动 React Native 的性能改进。Exact 会接入 Expo 现有的云服务,用于构建、更新、监控和托管应用。

所以眼下更准确的理解是:Exact 是 Expo 团队探索的另一条路线,和 Expo/React Native 并行,不是替代。仓库在 11 月 2 日才创建,作者说它最初是个人项目,后来 Expo 另一位联合创始人 James Ide 等人陆续加入。

编辑分析:这套取舍值不值得

以下是 WarpNav 编辑基于公开资料的分析,不是作者或 Expo 的观点。

它押注的前提是「写代码的主要是代理」。如果这个前提成立,Contract 的很多限制就从缺点变成优点:人类开发者会嫌不能写循环、不能随手 await 很别扭,但对代理来说,可写的东西越少,犯错的空间越小,编译器能检查的越多。能控制时钟、能读界面状态树、测试脚本跨平台通用,这些都是在缩短代理「改代码 → 看结果 → 再改」的循环。这和最近「为代理重新设计工具」的趋势一致,比如 Cloudflare 为 AI 代理重造浏览器引擎的 Kitesurf。

最大的代价是「新语言」。Contract 不在任何模型的训练数据里。作者自己也承认,在 AI 编写基准里 Astro 仍然更便宜、更快,并认为如果模型学会了 Exact,差距会缩小。这其实是个先有鸡还是先有蛋的问题:模型要等足够多的 Contract 代码出现才会学会它,而开发者要等模型写得好了才愿意用。编译器的「教学式报错」是在绕开这个问题,效果如何还需要更多人验证。

生态和可迁移性要打问号。Exact 没有 React 层,意味着 React 生态里大量现成的组件库、经验和人才不能直接拿来用;反过来,用 Contract 写的界面也很难搬回 React。对一个 pre-alpha、API 每天在变的框架来说,这种绑定风险要算进去。设计文档不公开,也让外部开发者更难判断某个限制是暂时的还是永久的。

TypeScript 和 Rust 可以混用,是一个务实的设计。作者的观点是,多数真实应用的业务逻辑用 TypeScript 写更实际,因为人和代理都能更快迭代;性能热点再用 Rust 写。他还提出一个个人猜想:Claude Code(TypeScript)比 Codex CLI(Rust)用起来更顺手,部分原因就在这里。这只是作者的推测,但反映了他的取舍:Rust 负责框架底层的速度,迭代速度留给应用层。

现在适合谁试。综合来看,现阶段适合有 Mac、愿意从源码折腾、想研究「代理怎么写应用」的开发者,或者有一个小型 iOS 应用、对启动速度和流畅度非常在意、能接受随时重写的人。作者提到有一位早期测试者当天就把 iOS 应用迁了过去,但这是个例。需要长期维护、要上 Android 商店、团队主要靠 React 经验的项目,现在不适合押注。

想试试的话

官方快速入门在 Apple 芯片 Mac 上验证,Linux 也可以运行网页开发流程和 Linux 原生程序。要把同一应用跑到网页、macOS 和 iOS 模拟器,可在 Mac 上准备这些工具:Rust(通过 rustup)、Bun 1.4.2(不需要 Node 和 npm)、Google Chrome(代理通过无头 Chrome 驱动网页端),以及构建 macOS 和 iOS 需要的 Xcode 27.1 或更高版本;TypeScript 应用在原生平台运行还需要 Hermes,下面的 setup 会安装并校验相应的预编译包。在终端运行:

git clone https://github.com/expo/exact.git
cd exact
bun scripts/exact.mjs setup
bun scripts/exact.mjs new ../hello

创建出来的应用会带一份 docs/start-here.md,README 说这是唯一必读的指南。

README 还给了一段可以直接交给 Claude Code 的提示词,让代理自己克隆仓库、做一个待办应用、写测试,并在网页、macOS 和 iOS 模拟器上跑通。仓库记录的一次早期测试里,在已有 Hermes 和 Cargo 缓存的机器上,一个新代理大约用 57 分钟完成,其中约 25 分钟花在首次构建 macOS 和 iOS 上,之后的构建只要一两分钟。这同样是项目自己的记录。用 Codex 或 Cursor 也可以照着做,但 README 的示例是以 Claude Code 为例写的。

如果你只是想把现有网页快速做成桌面应用,不需要折腾新框架,站内介绍过的 Pake 门槛低得多;Exact 解决的是另一类问题:从头写一个原生应用,并让代理全程参与。

项目信息(GitHub API 核对于 2026 年 11 月 12 日):仓库 expo/exact,2026 年 11 月 2 日创建,主要语言 Rust,MIT 许可证,约 3,126 Star、71 Fork,尚无 Release,默认分支最近提交为 11 月 12 日 17:30(台北时间)。

项目地址:expo/exact
模板仓库:expo/exact-templates

资料来源

核对日期:2026 年 11 月 12 日

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...