Skip to content
AI SI Daily
English

搜索全站

↑↓ 选择 · Enter 打开 · Esc 关闭

○ 工具介绍

长桥 nsh(Native Shell)解读:用 TSX 写原生界面的 Rust 跨平台 UI 框架,前端该关注什么

长桥开源的 nsh(Native Shell)对前端意味着什么:TSX + signal、各平台原生控件、热更新、面向 AI Agent 的工具链,以及与 React Native、Flutter、Tauri 的对比。

滴滴点到实测: Debian 13 虚拟机,8 vCPU,15 GB 内存,无头 Google Chrome 156(2026-11-01)。未测试 iOS、Android、macOS、Windows 及 GTK 桌面窗口。
这是一篇工具介绍:内容整理自官方网站、官方文档和 GitHub README,本站未对其做实测。功能和价格以官方页面为准,来源见文末。

10 月 28 日,长桥工程师 Jason Lee(@huacnlee)在 X 上宣布:“Longbridge 接下来会将所有手机客户端里面的 H5 逐步淘汰迁移改造,改用 NSH 来实现”。做 App 内嵌 H5 的前端可以留意一下。

nsh(Native Shell)是长桥开源的跨平台 UI 框架,支持用 Rust、TSX 或两者混写。渲染层在 iOS、Android、macOS、Linux 上调用系统原生 UI 控件;Windows 端用 Direct2D 自绘;Web 端输出普通 HTML 元素。仓库采用 Apache-2.0 许可,截至发稿刚建仓 18 天,发了 4 个版本,其中两个带有破坏性 API 变更。

想用一套 TSX 或 Rust 代码覆盖手机、桌面和 Web,又不想套 WebView,可以花个周末用 nsh 做个原型。但目前 API 变动频繁,还不适合直接上生产环境。

nsh 是什么

项目定位是 “a Rust-first native UI framework”。按官方文档的说法,应用可以用 Rust 写(编译成原生代码),也可以用 TSX 写(由 QuickJS 运行,Web 端跑在浏览器自己的 JS 引擎上),或者两者混写。底层共用一个 Rust 引擎:所有平台的布局都由 Taffy 计算(支持 Flexbox 和 Grid),架构文档提到响应式核心沿用了 Solid 1.9 的算法。

各平台后端与最低版本要求如下(数据来自对比文档):

目标平台 由谁绘制界面 最低要求
iOS UIKit iOS 15
Android Android View Android 9(API 28)
macOS AppKit macOS 14
Windows NSH 自绘(Direct2D/DirectWrite) Windows 10 1809
Linux GTK 4 GTK 4.14
Web 用 CSS 样式化的 HTML 元素 现代浏览器
GPUI 把 nsh 应用嵌进 GPUI / GPUI Kit 应用 桌面端

提交记录最多的作者是 Jason Lee。他在 X 上解释过“Native”的含义(2026-10-25 15:43,北京时间):“除 Windows 之外,各平台都不是自绘 UI”,输入框、滚动、文本选择、输入法、无障碍都直接用系统自带的能力。

前端视角:在 nsh 里怎么写界面

我们用 nsh 0.3.0 执行 nsh init my-app --template ts,生成了下面这个计数器模板,原样照录:

import { mount, signal, Text, View } from "nsh";

function App() {
  const count = signal(0);
  return (
    <View class="flex-1 pt-[env(safe-area-inset-top)] pr-[env(safe-area-inset-right)] pb-[env(safe-area-inset-bottom)] pl-[env(safe-area-inset-left)] items-center justify-center gap-4 bg-background">
      <Text class="text-3xl font-semibold text-foreground">{count()}</Text>
      <View
        onPress={() => count.update((c) => c + 1)}
        role="button"
        class="rounded-(--radius) bg-primary px-5 py-3 active:bg-primary/90"
      >
        <Text class="text-lg text-primary-foreground">Tap</Text>
      </View>
    </View>
  );
}

mount(App);

模板自带一个可无头运行的测试:

import { expect, open, test } from "nsh/test";

test("counts taps", async () => {
  const app = await open("./App.tsx");
  expect(app.texts()).toContain("0");
  await app.press("Tap");
  await app.press("Tap");
  expect(app.texts()).toContain("2");
});

习惯了 React 或 React Native,上手时会遇到几个明显差异:

  • 没有 React,也没有虚拟 DOM。 架构文档写明,组件函数只执行一次,后续只更新数据绑定,没有组件重渲染和虚拟 DOM diff。写过 Solid 的人对 signal()、count()、count.update() 会很熟悉;只用过 React Hooks 的话,得先把组件重渲染的心智模型扭转过来。
  • 不是 HTML。 标签用 View、Text,事件用 onPress,看着像 React Native。Jason Lee 在回复里说:“不是 HTML + CSS 这是我们特有的 DSL,只是看起来像 TSX”。早期版本里仿 React Native 的 API,在 v0.2.0 已经换成了 nsh 自己的命名。
  • 样式靠 Tailwind class。 class 接收 Tailwind 工具类,style={{ … }} 接收驼峰命名的样式对象;主题沿用了 shadcn/ui 的 token(如 bg-primary、text-foreground)。Tailwind 类在运行时由 Rust 直接解析,不需要过一遍 PostCSS。
  • 不依赖 Node.js。 单个 nsh 可执行文件包揽了整个构建链路:Oxc 擦除类型、自研编译器转换 JSX、rolldown 打包,最后编译成 QuickJS 字节码。运行 nsh check 时会从 npm 下载一次 TypeScript 原生编译器做类型检查,同样不需要装 Node。
  • 基础组件不带样式。 nsh/base 只提供导航、对话框、菜单、标签页、表格、编辑器等组件的交互逻辑,长什么样由业务方自己写。设计目标文档明确写了,带样式的组件库交由应用层或社区去建,官方不做类似 shadcn 的现成皮肤。

快速上手

以下命令整理自入门文档和发布说明:

# macOS / Linux(也可用 Homebrew:brew install longbridge/tap/nsh)
curl -fsSL https://nsh.dev/install.sh | sh
# Windows PowerShell:irm https://nsh.dev/install.ps1 | iex

nsh init my-app --template ts          # 也可选 rust、mixed
nsh run my-app                         # macOS 用 AppKit,Linux 用 GTK,Windows 用 Win32
nsh run my-app --target web            # 也可选 ios、android、gpui、catalyst
nsh test my-app                        # 无头测试
nsh package my-app/App.tsx --target web

官方预编译包目前提供 Linux x86_64、macOS arm64、Windows x86_64 三个桌面版本,外加 iOS 和 Android 的嵌入包。v0.3.0 发布页没有提供 Intel Mac 版本。

我们在 Linux 上实际跑了什么

2026 年 11 月 1 日,我们在一台 Debian 13 虚拟机里安装了预编译的 nsh 0.3.0,测试了命令行工具和 Web 构建产物(未在手机、Mac 或 Windows 真机测试):

  • 安装后的发行包占用 451 MB 磁盘空间。
  • nsh init 生成上文展示的模板;执行 nsh build 输出 “1.1 KB js, 3.0 KB bytecode, 6ms”。
  • nsh test 无头模式跑通模板测试:“1 test: 1 passed, 0 failed (322ms)”。
  • nsh package --target web 产出一个 13.1 MB 的静态目录,其中 nsh.wasm 占了 13.6 MB,gzip -9 压缩后为 4.7 MB。
  • 用无头 Chrome 156 打开页面显示正常,点击两次按钮计数变为 2。检查 DOM 结构,里面只有 6 个 div 和 2 个 span,没有用到 canvas,每个节点都挂着内联的 left、top、width、height 样式。
  • GTK 桌面窗口没跑起来:Linux 运行时依赖 WebKitGTK 6.0,测试虚拟机安装该依赖失败,桌面端未能跑通。

相关日志和截图已归档在证据目录。wasm 体积要结合版本看,见下一节。

Web 端:确实是 HTML,但布局归 NSH 管

Jason Lee 在 X 上说 nsh 的 Web 版 “not the wasm. All are HTML + JavaScript”(2026-10-19 20:22,北京时间)。评论区有用户 @PeterKogo2 追问:“Why is there a 1.3mb wasm loaded and most of the frametime is spent in wasm?”

这两句话其实不矛盾。渲染出来的节点确实是原生 HTML,滚动、选字、输入都走浏览器默认行为;但按照 Web 文档的说明,组件状态、布局计算和更新调度依然由编译成 WebAssembly 的 Rust 引擎接管。我们实测看到的 DOM 证实了这一点:节点位置由 Rust 里的 Taffy 算好,直接写成绝对定位坐标,浏览器自身的 CSS Flexbox 并不介入布局。前端打开 DevTools 调布局时,看到的会是算好的像素偏移量,而不是 display: flex。

产物大小要分版本看。按 v0.3.0 的文档,TSX 应用在 Web 端会把 QuickJS 一起打进 wasm,体积“约 3.5 MB,gzip 后 1.2 MB”(我们实测用 v0.3.0 打出来的包大得多,具体原因尚未查明)。到了 10 月 28 日(v0.3.0 发布之后),PR #603 合入主干,改成让 TSX 直接跑在浏览器自带的 JS 引擎上,最新文档随之把仅含核心组件的应用下载体积改写为“约 1.1 MB”。截至 11 月 1 日,这个改动还没发正式版。

热更新与开发流程

执行 nsh run 和 nsh dev 会启动支持模块热替换的宿主环境。开发服务器文档给出的数据是:应用 TSX 改动补丁耗时“远低于 1 毫秒”,从保存文件到界面更新“约 120 毫秒”,未改动的组件会保留实例和 signal 状态;修改 Rust 代码则会触发重新编译并重启应用。以上为官方文档数据,我们这次没有实测热更新耗时。

用 AI 写,也为 AI 而写

nsh 从开发方式到应用场景都和 AI 绑得很深:

  • 方便 Agent 读取的文档与类型。 官方文档直接提供 llms.txt 和 llms-full.txt,所有页面都有对应的 Markdown 版本。框架内全部元素、属性、样式键的 TypeScript 声明均由 Rust 源码自动生成到 .nsh/types 目录下,方便 Agent 写代码时直接通过编译器做类型检查。
  • 用 Tailwind 减少 token 消耗。 Jason Lee 写道(2026-10-20 21:54,北京时间):“for AI, the Tailwind API is less token cost.” 这是他个人的判断,我们没见到测量数据。
  • 动态下发 AI 生成的界面。 宿主 App 支持下载带签名的 .nshpkg 包(内含 TSX 代码)并在沙箱中运行。沙箱文档列明了内存上限、单次调用耗时、节点数量等限制,以及宿主下发的权限控制。Jason Lee 在发布帖(2026-10-19 18:57,北京时间)里提到,当周就会在长桥手机端接入 nsh,“主要解决 AI 动态生成模块支持”。
  • 大部分提交由 AI 参与。 我们克隆下来的仓库共有 640 个 commit(截至 2026-11-01 21:20,北京时间),其中 518 个带有 AI 共同作者标记或 “Generated with Claude Code” 字样。出现频率最高的是 “Co-authored-by: Claude Opus 5.5”(353 次),Codex、Devin、GitHub Copilot 的 Agent 也有参与。仓库里有一份 614 行的 AGENTS.md,CLAUDE.md 里只有一行指向它的引用。Jason Lee 还在 X 上提到 “NSH 项目每天有超过 50 个 PRs”(2026-10-29)。

对前端团队而言,把创建项目、类型检查、无头测试、打包塞进同一个命令行工具,确实方便让 Agent 自己写完页面自己跑通验证。但反过来,靠 Agent 这么快写出来的 API,变起来也会一样快。

和 GPUI、GPUI Kit、gpui-component 的关系

在做 nsh 之前,长桥已经在维护 GPUI Kit(原名 gpui-component,GitHub 约 1.88 万星),这是为 Zed 编辑器的 GPUI 打造的组件库,同时他们还维护着自己的分支 GPUI Fast。GPUI 走的是纯 GPU 自绘路线。

nsh 文档解释了另起炉灶的原因:这个项目最初是给长桥手机 App 做插件层,起点是 GPUI Shell。但团队发现在手机上搞自绘,就得把系统现成的文本选择及弹出菜单(拷贝、共享、翻译、查询)、输入法、无障碍等功能全部重造一遍。Jason Lee 在 X 上也谈到了同样的问题:移动端离不开原生的文本选择、翻译和自动填充,对多点触控和功耗也更敏感,GPUI 的 immediate mode 模式在这些场景下比较吃亏。

目前两条线的定位很清晰:追求自绘的桌面端继续用 GPUI Kit;nsh 里的 nsh/base 延续了 gpui-base 行为与样式分离的设计,并且提供了 GPUI 后端,可以把 nsh 应用直接嵌进 GPUI Kit 桌面应用里。至于有用户 @tdomhan 询问 GPUI Kit 后续是否会停止维护,我们没找到公开回复。

nsh 与 React Native、Flutter、Tauri、Electron 对比

nsh React Native Flutter Tauri Electron
界面由谁绘制 平台原生 UI(Windows 自绘) 平台原生 View 自带引擎 系统 WebView 内置 Chromium
写界面用 TSX + signal,或 Rust JS/TS + React Dart 任意 Web 框架 任意 Web 框架
原生 App 里的 JS 运行时 TSX 用 QuickJS;纯 Rust 应用没有 有 无 用 WebView 的 Chromium + Node.js
移动端 iOS 15+、Android 9+ iOS 15.1+、Android 7+ iOS 15+、Android 7+ 支持(Tauri 2) 不支持
桌面端 macOS、Windows、Linux 需另外的 macOS/Windows 项目 macOS、Windows、Linux macOS、Windows、Linux macOS、Windows、Linux
Web HTML 元素 通过 react-native-web Canvas 本身就是网页 本身就是网页
许可证 Apache-2.0 MIT BSD-3-Clause MIT 或 MIT/Apache-2.0 MIT

数据来源:nsh 对比文档(引用了 React Native 0.76 与 Flutter 支持平台)、Tauri 文档、Electron 文档 及各项目 GitHub 许可证。

nsh 官方文档自己也划出了不适用场景:要求多端像素级一致,去用 Flutter 或 Slint;依赖庞大第三方生态,去用 React Native、Flutter 或 Qt;遇到持续高频刷新的界面,去用自家的 GPUI Fast。

在技术选型上,Jason Lee 对 Web 套壳方案态度鲜明,10 月 26 日(09:25,北京时间)他在 X 上写道:“如果你还在考虑 Electron, Tauri 这些工具,那应该赶紧放弃”。这代表项目维护者的个人倾向,并非客观评测结论。

性能:目前只有项目方数据

我们未做独立性能测试,以下均为官方公布的数据:

  • 对比文档引用的 nsh-perf-bench 基准测试(Linux 环境,500 行行情表,GTK 后端):每秒推送 1,000 条行情时,NSH Rust 占用单核 18% CPU,GPUI Fast 占 20%;加压到每秒 20,000 条时,GPUI Fast 占 25%,NSH 升至 73% 到 78%。
  • Jason Lee 晒出的 Gallery “Stocks” 示例运行数据:M3 Mac 上跑满 120 FPS、CPU 占用 33% 到 36%;Linux + NVIDIA 环境下 117 到 120 FPS、CPU 占用 31% 到 32%;Windows 上 144 FPS、CPU 占用 36% 到 43%。

局限与风险

  • API 变动频繁。 10 月 22 日的 v0.2.0 和 10 月 26 日的 v0.3.0 均包含破坏性变更。向后兼容文档虽然承诺 “an app built for a compatible release runs on every later release, unchanged”,但具体的“兼容版本”列表记录在单独的 nsh-compat 里,我们这次没有核查,暂不确定当前覆盖到了哪个版本。
  • 立项时间极短。 仓库第一个 commit 提交于 10 月 14 日。截至 11 月 1 日共有 914 星、72 个 open 状态的 issue。GitHub API 识别出的许可证状态为 “NOASSERTION”,不过仓库里放的是 Apache-2.0 协议文件。
  • 跨平台不等于一次出所有安装包。 正如用户 @trymorewz 在评论区提醒的:“‘跨平台’也不等于一次编译出所有安装包,桌面应用仍需在对应系统打包。”
  • Windows 端非原生控件。 Windows 平台由 NSH 基于 Direct2D 自绘实现。
  • Web 运行时比纯 HTML 重。 前面展示了实测的 wasm 体积数据,准备上生产前务必拿当前版本的构建产物实测一下体积。
  • Linux 端完成度还不高。 有用户反馈“linux环境下bug有点儿多”;还有用户提到 llms.txt 没有及时更新指向最新版本,导致他的 Agent 一直锁在旧版本上写代码。
  • 鸿蒙支持尚未落地。 Jason Lee 说社区已经有人提了 HarmonyOS 的 PR,但他还在考虑要不要合入。

X 上的反应

我们看到的讨论主要集中在 Jason Lee 的推文评论区,大多是中文:

  • @xiaoshan0413 总结:“重性能拼定制就选GPUI,要快要跨端就选Native Shell。”
  • @maddada 吐槽:“TypeScript feels like ‘ew’ for desktop or mobile apps 😅 Any performance comparasions between Native Shell and GPUI?”
  • 写过 C++ Skia 跨平台框架的 @faywanghq 问:nsh 是不是只用平台提供的容器 View、内部子 View 自绘?否则这么多平台怎么保证能力一致。
  • @sufunds 晒出了自己基于 nsh 写的 macOS + iOS 应用 Vela,配合 Tailscale 让 iPhone 直接访问 Mac 上的本地开发服务。
  • @thejingtao 说:“我在用 NSH 做 Generative UI 了,效果非常好”。
  • @emojiiii007 问:nsh 既然构建成原生代码,动态更新怎么做?答案就是前文提到的下发签名 TSX 包。

对前端意味着什么

回到开头那条淘汰客户端 H5 的推文,Jason Lee 的原话后半段是:“以后将不再需要用前端来开发这些动态更新的手机界面。采用 NSH 既能获得 Native 的体验,又能继续如同 H5 一样动态更新且高效开发。” 除了这条推文,我们没有找到具体的迁移时间表。

真要切过去,前端手里的 TSX、Tailwind、Flexbox 布局经验以及写单测的习惯都能直接复用;需要扔掉的是 React 框架本身、依赖浏览器 DOM 的 npm 包,以及“靠浏览器算 CSS 布局”的调试习惯。

我们目前的看法:nsh 想同时拿到 H5 的动态下发和各平台的原生控件,长桥自己也在往里押注。靠 Agent 驱动的开发速度是它的优势,也是现阶段最大的风险。想尝鲜的话,可以先锁定版本号,用 TSX 写个独立页面试试,等兼容性记录稳定下来,再讨论存量项目的迁移。

一手资料