Snapchat 开源全新跨平台框架 Valdi ,一起来搞懂它究竟有什么特别之处

作者:恋猫de小郭日期:2025/11/17

最近看到好几篇在推 Valdi 的文章,大致意思就是 「RN/Flutter 的地位将受到威胁」,「Valdi 将成为全新的跨平台流行架构」云云,这不仅就让我好奇这个新框架有什么魔力,还能在 2025 的跨平台领域玩出新花样?

首先,Valdi 是由 Snapchat 开源的跨平台框架,其核心技术已在 Snap 的生产应用中验证长达 8 年,号称在不牺牲开发速度的前提下提供原生性能 ,那它是怎么做到的?

简单来说,Valdi 是一个 “用 TypeScript(TSX)写 UI,然后编译成原生视图(iOS/Android/macOS)” 的跨平台 UI 框架,所以它说了 Valdi 不依赖 WebView 和 JS Bridge ,也就是说 Valdi 就是一个将 TS 转化为原生布局的编译支持?

答案肯定不是,这也是它和 RN 不同的地方,Valdi 是在编译期完成的原生转化。

虽然 Valdi 采用了“编译时”模型,会将声明式的 TS 直接编译为平台原生视图(iOS/Android/macOS),但是重点在于:

“Optimized layout engine – C++ layout engine runs on the main thread with minimal marshalling overhead.”

也就是它虽然编译成原生控件,但是它的布局并不走原生布局,它是通过自己的 C++ 布局引擎来完成布局的,当然其实新架构的 RN 现在也都有自己的布局策略,比如 Fabric 取代了原本的 UI Manager,支持 React 并发渲染和 Suspense & Transitions 。

而它另一个重要的特性就是 “Polyglot 模块” ,这个模块核心就是实现一个自动类型安全绑定系统,它充当了一个编译时外来函数接口 (FFI) 生成器,Polyglot 允许开发者“用 C++、Swift、Kotlin 或 Objective-C 编写性能关键代码” ,允许开发者在 Valdi 中构建完整的功能(包括后台处理),从而消除了特定平台的桥接代码 。

实际上从社区上提及的,就是 Polyglot 在架构上优于 React Native (RN) 的 (JSI) 和 Flutter 的平台通道 (Platform Channels),理论应该和 Flutter 的线程合并后的 FFI 差不多。

所以,也就是搞懂了这两个东西,我们就大概知道了 Valdi 是什么了。

布局

Valdi 布局系统的底层支撑是一个“优化的 C++ 布局引擎” ,并且最有意思的是,这个引擎“在主线程上运行” ,这也是这个框架的特色或者说争议点。

对于这个问题,Valdi 表示这是一个优势,理由是“最小化的编组开销” ,基础是该 C++ 引擎的效率极高,以至于在 UI 线程上直接运行布局计算的成本,低于将布局数据发送到后台线程并异步接收计算结果(涉及数据编组)的总成本

这其实是一种高风险又高回报的架构,这意味着 Valdi 的 C++ 效率必须极高且绝对可信。

而从这点也可以看出,Valdi 并不是直接调用系统的布局机制(例如 iOS Auto Layout 或 Android ViewGroup 的 measure-layout),而是采用了自定义 C++ 布局引擎来计算视图尺寸与位置,可以简单理解为:开发者以声明式 TS 写布局,Valdi 的布局引擎负责把这些声明转化为原生视图的 「尺寸/位置/层级」。

整个流程可以大致推论为:

  • TSX 写组件 <view padding={10} backgroundColor="red"><label … /></view>
  • 在编译/运行时,Valdi 的 TSX → 中间结构 → 原生视图映射机制,会建立一个视图树(native views),但这些视图的尺寸与位置不是简单依赖平台默认布局,而是由 C++ 布局引擎计算
  • 布局引擎接收节点树、样式(margin/padding/flex etc)
  • 引擎在主线程运行,计算每个视图的尺寸和位置,输出布局结果,然后原生视图被 “inflate”/复用(Valdi 有全局视图池化机制
  • 当数据状态改变(组件 state 或 viewModel 更新)时,仅受影响的子组件重新渲染,其对应的视图树/布局会被重新计算/更新,而不会强制父视图全部重绘(“Components re-render independently without triggering parent re-renders”)

这里有一些官方特别提到的点:

  • Automatic view recycling : 一个 Global view pooling system ,这个系统会复用现有的原生视图对象(例如 UILabelUILabelUILabel, TextViewTextViewTextView),而不是创建新对象,从而减少原生控件 inflate/销毁开销
  • Viewport-aware rendering :只有可见的视图节点才被 inflate,从而在滚动/大量列表场景中降低资源消耗,这也是 Snapchat 这样的社交媒体应用最需要的能力
  • Optimized component rendering : Valdi 组件会“独立地重新渲染,而不会触发父组件的重新渲染” ,从而实现快速、精细化的增量 UI 更新
  • marshalling overhead minimal :通过 C++ 布局引擎减少跨语言通信成本

根据目前代码看,Valdi 转化的原生控件应该还是传统 Android View 和 UIKit 体系 ,而 Valdi 的核心之一就是打磨自己的 C++ 布局引擎,虽然用的原生控件,但是整个布局流程都在 Valdi 自己内部实现,只有绘制流程回归了平台,这也是为什么是 Snapchat 会说:“Flexbox layout system with automatic RTL support.”

Polyglot

Polyglot 是 Valdi 的原生集成解决方案的另外一个关键,也是 Valdi 最重要的架构特性,因为 Polyglot 可以在 TypeScript 和原生平台之间生成类型安全的绑定 ,通过绑定,可以让 TS 和普通函数一样与原生代码双向通信,允许“复杂的数据结构和回调” 在 TS 和原生代码之间安全传递。

并且 Polyglot 不是一个运行时桥接,而是一个编译时 FFI 生成器,从 TS 到 myNativeModule.doThing() 的调用,都可以被编译为对底层 Swift/Kotlin 实现的_直接、类型安全、零开销的同步函数调用_ 。

这个实现主要是为了消除了困扰 RN 和 Flutter 集成的所有样板代码和序列化开销,Snapchat 曾经开源的 djinni 工具 (用于生成 C++ 和 Java/Obj-C 之间的绑定)感觉大概率是该 Polyglot 的技术前身。

换言之,Polyglot Modules 在 Valdi 应用中,可以在需要性能或者原生平台特性(camera、硬件加速、第三方原生库)的时候,用 C++/Swift/Kotlin/Obj-C 等语言编写模块,然后通过自动生成的绑定,使得这些模块在 TS 层可以被安全调用。

举个例子,比如关于 Webview 支持,虽然 Valdi 内部已经实现了这个功能,但它没有包含在开源项目,用户需要通过定义一个带有 ExportProxy 的接口,然后在原生实现这个方法 :

image-20251112135413760

简单来说,可以通过 Native 代码将创建一个标记为 ExportProxy 的 TypeScript 接口实例,然后实例可以通过组件上下文传递给 TypeScript ,具体为:

TypeScript:

1// @Context
2// @ExportModel({ios: 'SCMyComponentContext'})
3interface Context {
4  serverURL: string;
5}
6
7// @Component
8// @ExportModel({ios: 'SCMyComponentView'})
9class MyComponent extends Component<any, Context> {
10  onCreate() {
11    // Will print http://api.server.com in the console
12    console.log(this.context.serverURL);
13  }
14}
15

Native :

1// Instantiate the context data structure
2SCMyComponentContext *context = [[SCMyComponentContext alloc]
3    initWithServerURL:@"http://api.server.com"];
4// Instantiate the view with the context passed as parameter
5SCMyComponentView *view = [[SCMyComponentView alloc]
6    initWithViewModel:viewModel
7     componentContext:context];
8

详细可见:github.com/Snapchat/Va…

当然,如果在 UI 层面,这还分为你想把 WebView 放到 UI 构建树里,还是仅仅显示在用户 UI 上方,如果是想把 WebView 嵌入到视图结构里,就需要需要创建一个自定义视图,整体会更麻烦一些:

另外还有比如你需要一些平台调用,如蓝牙、摄像头,那么 Valdi 也可以直接调用本地代码,本地代码也可以调用 Valdi 代码:

  • 如果想要一个带有嵌套实时摄像头视图的 Valdi 用户界面,可以添加一个 <custom-view> 将它指向 iOS/Android 实时摄像头视图
  • 如果想启用/禁用蓝牙,可以原生处理此操作,然后公开一些函数,这些函数可以作为上下文的一部分传递给 Valdi 组件,然后 TS 代码就可以根据需要调用它们

如果需要更形象的使用,具体代码类似:

  • 在 TypeScript 调用 Native 代码
1/**
2 * @Context
3 * @ExportModel({
4 *   ios: 'SCYourComponentContext',
5 *   android: 'com.snap.myfeature.YourComponentContext'
6 * })
7 */
8interface YourComponentContext {
9  callMeFromTS?();
10}
11/**
12 * @Component
13 * [...]
14 */
15class YourComponent extends Component<YourComponentViewModel, YourComponentContext> {
16  onMyButtonWasTapped() {
17    // Calls callMeFromTS: on the SCYourComponentContext (if it has been configured)
18    this.context.callMeFromTS?.();
19  }
20}
21
  • 然后在 Kotlin 定义好原生实现
1package com.snap.myfeature.YourComponentContext
2
3class SCYourComponentContextImpl {
4    val onDone: (() -> Unit)?
5    // ...
6}
7
8//////////
9
10// So you can instantiate YourComponentContext and configure it with the callMeFromTS block:
11val componentContext = YourComponentContext()
12componentContext.callMeFromTS = {
13  // Will be called when this.context.callMeFromTS() is called in TS.
14  print("Hello from Kotlin")
15}
16
  • 在 TypeScript 定义好接口
1interface YourComponentContext {
2  callMeFromTS?(completion: (arg: string) => void);
3}
4class YourComponent extends Component<any, YourComponentContext> {
5  onMyButtonWasTapped() {
6    this.context.callMeFromTS((arg) => {
7      console.log('the native code called the completion function with arg:', arg);
8    });
9  }
10}
11
  • 然后在 Kotlin 调用
1componentContext.callMeFromTSWithCompletion = { completion ->
2  // This will call the TS callback and provide the given value.
3  completion(@"I got you loud and clear");
4}
5

可以看到,Polyglot 提供了一套非常方便的调用机制,这也是 Valdi 对自己性能如此有自信的来源。

其他

关于 Valdi 的其他优势还有:

  • 灵活渐进式采用:目前的 Valdi 实现上,可以让开发者在已有原生 App 中逐步引入 Valdi,也可以在 Valdi 中插入原生视图,这让 Valdi 的接入和使用门槛相对变低不少,在混合开发领域有些许优势
  • 后台处理 :支持 worker 线程实现多线程执行,许开发者使用 worker 线程在 Valdi 中构建完整的功能 ,这也是一个有意思的点,比如和 “Polyglot 模块” 结合,开发者可以在一个 TS worker 线程编写业务逻辑,而线程自身又可以通过 "Polyglot" FFI 对 C++/Swift/Kotlin 代码进行直接、零开销的调用,类似更便捷版本的 Dart isolate Group/backgroud
  • 支持 hot relaod ,不用多言,开发必备
  • 完整的 VSCode 调试: 可以直接在 VSCode 中设置断点、检查变量、分析性能和捕获堆转储

问题

那么聊了这么多,相信大家应该了解 Valdi 是怎么实现的跨平台了,那么该简单聊聊它的问题了:

  • 社区待发展,虽然 Polyglot 很便捷,但是第三方平台插件总要有人写和封装,大部分开发者其实并不具备多平台的开发能力,所以社区插件生态完善是它未来是否可用的一个很重要的标志
  • 文档混乱不全,存在歧义也是目前的主要问题之一
  • 开源还处于 beta 阶段,例如目前 package.json 列出了 @snapchat/eslint-plugin-vivaldi 还是一个私有 NPM 依赖,类似的还有 Bazel 构建脚本失败,问题也是构建脚本正试图使用 SSH 从一个私有 GitHub 仓库(名为 @valdi)抓取依赖,可以看出来本次开源还是相对仓促:

所以,目前看来 Snapchat 确实有着出色的设计,比如自定义的 C++ 布局引擎和 Polyglot ,但是它需要走的路还长,毕竟作为跨平台框架,它不再只是需要面对来自内部的压力,Valdi 更需要得到社区的支持,并且有更多丰富的案例来帮助开发者投入其中,重要的是,需要让开发者看到 Snapchat 持续维护开源的决心的行动。

那么,你觉得 Valdi 如何?你会尝试吗?

参考链接


Snapchat 开源全新跨平台框架 Valdi ,一起来搞懂它究竟有什么特别之处》 是转载文章,点击查看原文


相关推荐


Java游戏高级编程 | 深入探索游戏引擎与优化技巧
mfnart_2822025/11/15

在线编译C语言|探索在线编译器的优势与应用在线编译C语言是一项非常实用的技术,它使得程序员能够在没有本地开发环境的情况下直接在浏览器中编写、调试和执行C语言代码。在线编译器通过提供一个即时反馈的开发环境,大大提高了学习和工作的效率,尤其对于初学者而言,更是降低了编程的门槛。相比传统的桌面编译器,在线编译器的优势在于其便捷性和灵活性。用户不需要安装任何开发工具,只需在浏览器中输入代码,点击“编译”按钮,就可以立即看到运行结果。这种即时性大大减少了开发中的等待时间,尤其是在调试阶段,可以快速查看修改


前端图形引擎架构设计:双引擎架构设计
猪猪拆迁队2025/11/14

ECS渲染引擎架构文档 写在前面 之前写过一篇ECS文章,为什么还要再写一个,本质上因为之前的文档,截止到目前来说,变化巨大,底层已经改了很多很多,所以有必要把一些内容拎出来单独去说。 由于字体文件较大,加载时间会比较久😞 另外如果有性能问题,我会及时修复,引擎改造时间太仓促,只要不是内存泄漏,暂时没去处理。 还有很多东西要做。 体验地址:baiyuze.github.io/design/#/ca… 项目概览 Duck-Core 是一个基于 ECS(Entity-Component-Sy


GPT-5.1 凌晨突袭,奥特曼听劝!全网呼唤的人味回来了
新智元2025/11/13

「【新智元导读】今天,OpenAI GPT-5.1「全家桶」突然登场,Instant 和 Thinking 王炸组合同步上线。这一次,模型情商智商双核升级,不仅更聪明,而且聊天更有人味了。」 没有直播,OpenAI 一早放大招,让所有人猝不及防。 就在刚刚,GPT-5.1 正式发布,GPT-5 系列重大升级版登场! 一共有三个版本,目前已经上线了前两个: · GPT-5.1 Instant :最常用的模型,语气更亲切、更智能,更善于遵循指令。 · GPT-5.1 Thinking :先进的推理模


李飞飞最新长文:AI的下一个十年——构建真正具备空间智能的机器
机器之心2025/11/11

就在昨晚,关于其投身的空间智能,斯坦福大学教授李飞飞发表了一篇长篇博客《From Words to Worlds: Spatial Intelligence is AI’s Next Frontier》。 在文中,李飞飞详细解读了「空间智能究竟是什么?它为什么重要?我们如何构建它?我们又如何使用它?」她同时阐述了真正的空间智能世界模型必须实现的核心框架:构建具有故事讲述者想象力的 AI、具备第一响应者流畅性的 AI 以及以科学精确性进行空间推理。 以下为全文翻译: 1950 年,当计算机还只


调用服务出现网络错误的问题排查与解决
360_go_php2025/11/10

在分布式系统和微服务架构中,服务之间的调用是常见的操作。然而,有时在调用某个外部服务时,可能会遇到网络错误或连接失败的情况。这类问题可能与网络环境、域名解析、DNS 配置等因素相关,给服务的稳定性和可用性带来影响。​编辑 本文将介绍如何排查和解决调用服务时出现网络错误的问题,最终通过 ping 命令确认错误接口的域名,并通过本地 hosts 文件检查和修改解析,解决了因 DNS 配置问题引起的服务调用失败。 1. 问题背景​编辑 在调用某个外部服务时,应用程序报错,提示无法访问目标服务,或者出现


一份实用的Vue3技术栈代码评审指南
至简简2025/11/8

CSS 优先使用 **scoped**  防止样式污染全局,每个组件样式必须局部化。 错误示例:无作用域 <style> .button { color: red; } </style>  不加 scoped 会影响全局所有 .button 正确示例:使用 scoped <style scoped> .button { color: red; } </style> 限制嵌套层级 ≤ 3 层 嵌套超过 3 层说明选择器设计有问题,建议拆分样式或使用 BEM。 错误示例:嵌套过深(5 层


Ant Design Landing模版使用教程-react-npm
I like Code?2025/11/4

特此鸣谢:https://github.com/ant-motion/ant-design-3.x-landing-page?tab=readme-ov-file 官网(不好用):https://landing.ant.design/docs/introduce-cn package.json代码如下 { "private": true, "entry": { "index": "./index.js" }, "dependencies": { "antd"


硬件岗位基础知识
千語萬言-2025/10/31

1. 为什么 I2C 要上拉电阻? 因为 I2C 芯片的物理输出是“开漏输出”,它自身无法输出高电平,需要上拉电阻来提供高电平。 a) 电气结构:开漏输出 I2C 总线上的每一个设备(主设备和从设备),其 SDA(数据线)和 SCL(时钟线)的物理输出级都是一个 开漏输出 或 开集输出 的电路。 b) 上拉电阻的作用 提供高电平、限流保护 2.解释 交流电 和 直流电 直流电 (DC - Direct Current) 含义:电流的方向和大小不随时间变化。 交流电 (A


C#.NET DbContext 池化机制深入解析:提升 EF Core 性能的关键
唐青枫2025/10/29

简介 DbContext 池是 Entity Framework Core 中的高性能数据库连接管理机制,通过重用已初始化的 DbContext 实例,显著减少创建和销毁上下文对象的开销,特别适合高并发场景。尤其在高并发场景(如 Web API)中,频繁创建和释放 DbContext 会导致: 性能瓶颈:实例化 DbContext 涉及反射、元数据初始化和连接池分配。 内存压力:频繁创建和释放会导致垃圾回收(GC)压力。 连接管理问题:不恰当的 DbContext 生命周期可能导致数


Stream flatMap详解与应用实战
IT橘子皮2025/10/26

Stream API 中的 flatMap方法是一个功能强大但有时会让人感到困惑的工具。它专为处理嵌套结构或"一对多"元素映射场景而设计,能将复杂的集合层次"拍平"为单一流。下面我们深入解析其核心原理、典型应用及实战技巧。 ​核心原理:先映射,后扁平​ flatMap的核心思想是 ​​"先映射(Map),后扁平化(Flatten)"​​ 。 ​映射(Map)​​:它对输入流 Stream<T>中的每个元素应用一个映射函数。这个函数的关键在于,它不接受一个普通的对象,而是必须返回一个 Strea

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0