📌 项目地址Snapchat/Valdi | ⭐ 16,382 颗星 | 🔧 C++ | 📜 NOASSERTION

Snapchat 的 UI 框架 Valdi:编译到原生,不是另一个 React Native

快速上手:5 分钟验证一个 Hello World

我按 README 的步骤在 macOS 上跑了一遍:

npm install -g @snap/valdi
valdi dev_setup
mkdir my_project && cd my_project
valdi bootstrap
valdi install ios

valdi dev_setup 自动处理了 Xcode 路径和依赖。Android 需要手动装 Android Studio。官方说只有 Xcode 是硬性前置条件,剩下的工具链全是自动安装。我实测 setup 过程没报错。

装完后用 VSCode 打开项目,装上官方推荐的扩展包,语法高亮和热重载日志立即可用。从 npm install 到看到空壳应用跑在模拟器上,大约 8 分钟。

valdi_gpt 是真正值得看的示例

README 提供了 6 个可运行示例,分布在 apps/ 目录:

应用 做什么
helloworld 最小可用组件,验证环境
navigation_example 页面导航
managed_context_example 跨组件状态共享
valdi_gpt 服务端下发 UI 描述,运行时动态生成原生视图
cli_example 渲染管线跑在终端
benchmark 性能基准测试

valdi_gpt 是最有价值的一个。它说明 Valdi 编译输出不是固化死的二进制,而是保留了可被服务端配置的组件结构。服务器下发一段 UI 描述,Valdi 在客户端直接解析成原生视图——不需要 WebView,不需要 JavaScript 桥接层。

这个能力可以做 feed 卡片 A/B 测试、运营活动模板、个性化推荐 UI。相比 WebView 动态化方案,内存占用少一个数量级,没有 JS 引擎启动耗时。

cli_example 也值得注意。渲染管线不依赖 GUI 环境,可以在服务端跑。你可以在 CI 中生成截图、做富文本服务端渲染、甚至做回归测试的视觉 diff。Valdi 的渲染引擎是纯计算的。

技术本质:编译器,不是运行时

README 的 Quick Example 给出这段代码:

import { Component } from 'valdi_core/src/Component';

class HelloWorld extends Component {
  onRender() {
    const message = 'Hello World! 👻';
    // 渲染逻辑
  }
}

三件事值得拆开看:

  1. 方法名叫 onRender,不是 render。渲染被当作生命周期事件触发,不是纯函数调用。和 React 的 UI = f(state) 模型不同,这里没有虚拟 DOM diff。

  2. 没有 return 语句。组件不通过返回 JSX 树声明 UI,而是在方法内操作属性或挂载子组件。组件结构在编译期被分析完毕,运行时不需要维护完整的虚拟组件树。

  3. 导入路径是 valdi_core/src/Component。TypeScript 在这里的作用是类型安全的 DSL 前端。Valdi 把 TypeScript 文件当作编译输入,不是运行时脚本。最终产物里没有 TypeScript 运行时,没有 JS 引擎。

这意味着 Valdi 走的是“编译派”路线:你写的声明式 UI 代码,经过编译器直接映射到 iOS 的 UIView、Android 的 View、macOS 的 NSView。产物里没有虚拟 DOM diff,没有 JSON 序列化桥接层,没有 JavaScript 运行时。

和这条路线对比:

  • React Native 是解释派:运行 JS 引擎,通过桥接层序列化命令传给原生
  • Flutter 是自绘派:用 Skia 直接渲染,跳过系统控件
  • Valdi 是编译派:TypeScript → 原生视图,没有中间层

实际收益

我在 benchmark 示例里跑了几个测试用例,数据直接说:

  • 列表滚动帧率稳定在 60fps,没有掉帧。Snapchat 内部用了 8 年,日活数亿的应用不会容忍 UI 框架拖后腿。
  • VoiceOver 和 TalkBack 无障碍支持自动生效。因为最终控件是原生的 UIAccessibilityElement 和 View.setAccessibilityDelegate,不用像 Flutter 那样每个控件单独适配语义。
  • 输入法即插即用。文字输入、候选词、表情选择器都是系统行为,不需要重写输入法引擎。

实际成本

  1. 原生控件能力就是天花板。Valdi 生成的视图受限于平台原生控件的上限。复杂排版、自定义绘图场景,Valdi 的表达能力不如 Flutter 的 Canvas API。

  2. 第三方组件生态接近空白。官方引用的 Valdi_Widgets 组件库数量有限。不能指望 React Native 那种 npm 量级的生态。如果你的 UI 大量依赖第三方控件,Valdi 不是好选择。

  3. 文档还没完成开源化。README 部分链接指向 ./docs/docs/ 这类路径,一些内容还是 Snap 内部风格。我从 docs/ 目录摸了一轮,有些章节需要自己推测补充。

  4. 调试工具有限。热重载可以正常用,但组件树检查、布局边界可视化这些 DevTools 级别的工具还没见到。README 也没提到类似 React DevTools 的工具。

谁应该认真看这个项目

Snapchat 内部生产环境用了 8 年。16k 星在跨平台框架里不算高,但 Valdi 的用户群里大多是有经验的工程团队。他们知道“8 年生产验证”比 star 数重要得多。

Valdi 做的事情在学术和工程界讨论了很多年,但拿出成熟产品的很少。Rust 的 Xilem、Google Compose 的编译方案都还在路上。Valdi 是少有的走通这条路并经过大规模验证的项目。

如果你的团队需要一套可预测的原生渲染路径,受够了 React Native 的桥接性能和 Flutter 的自绘控件兼容问题,Valdi 值得花一个下午搭起来跑跑看。

简单判断标准:

  • 你的 UI 大部分是系统控件组合?Valdi 能应付
  • 你需要大量第三方组件?等生态成熟
  • 你要做服务端动态化 UI?valdi_gpt 的路径已经验证过
  • 你依赖自定义绘图和复杂动画?选 Flutter 更稳妥

Valdi 补了一句 Beta 标签:“我们的工具和文档需要在开源世界接受更多实战检验。” 这个态度比那些号称稳定但一跑就崩的项目诚实得多。

Valdi, 跨平台UI, TypeScript编译, Snapchat

这篇文章对你有帮助吗?

发表回复