Transcript
00:00:00这是 Wterm,由 Vasell 开发的一款网页终端模拟器
00:00:03它直接渲染到 DOM,而不是使用 canvas。
00:00:06因此文本选择、浏览器搜索、
00:00:08以及屏幕阅读器都能直接兼容。
00:00:10它由 Zig 编写,编译成 12KB 的 WASM 二进制文件,
00:00:14此外还有一个由 LibGhosty 驱动的可选后端,
00:00:17即为 Ghosty 终端提供支持的同一引擎,
00:00:19这让它在浏览器中拥有完全的终端兼容性。
00:00:22但是,一个 12KB 的 WASM 二进制文件
00:00:24真的足以替代原生终端模拟器吗?
00:00:28大概不行,但请点击订阅,我们来一探究竟。
00:00:33网页终端如今几乎随处可见。
00:00:36在 GitHub Codespaces 等云端 IDE 中,
00:00:39在 Portainer 或 Qualify 等基础设施工具中,
00:00:41甚至在 VS Code 或 Cursor 等桌面 IDE 中。
00:00:44但它们都使用 Xterm.js 来实现,
00:00:47因为它已经存在很长时间了,
00:00:49基本上是事实上的默认方案。
00:00:51不过 Xterm 有个大问题。
00:00:52它渲染到 canvas 元素中。
00:00:54所以像选择文本
00:00:56或在页面中查找单词这样的操作,
00:00:58都必须从零开始重新实现,
00:01:00而且效果并不总是那么好。
00:01:02Wterm 采取了完全不同的方法,
00:01:04即渲染到 DOM,
00:01:05这意味着终端输出只是 HTML,
00:01:08浏览器基本上可以免费处理这些内容。
00:01:10但 Wterm 也能用这种 HTML 渲染方式
00:01:13做一些非常酷的事情,
00:01:14比如只重新渲染更新的那一行,
00:01:17而不是在每一帧中重新渲染整个终端。
00:01:20它还可以写在不同的框架中,
00:01:22比如 React 或 Vue。
00:01:23你可以更改主题。
00:01:24还有一个独立的 Wterm ghosty 包,
00:01:27它用 lib ghosty 替换了 Zig 调用,
00:01:29而且比另一个网页 ghosty 项目
00:01:31工作得更好,
00:01:33我们会在视频后面深入讨论这一点。
00:01:35但现在,让我们用一个简单的演示项目
00:01:37试用一下 Wterm。
00:01:38安装 React 版 Wterm 后,
00:01:40我已经导入了组件和 CSS,
00:01:43并在那边渲染了该组件。
00:01:45现在如果我运行该应用并进入浏览器,
00:01:48可以看到有一个终端。
00:01:49但如果我输入像 ls 这样的命令,
00:01:51什么也不会发生。
00:01:52这是因为它没有连接到
00:01:53另一台电脑来读取信息。
00:01:56让我解释一下。
00:01:57因为现在客户端并没有连接到后端,
00:01:59所以它没地方获取信息。
00:02:01我们需要做的是把它连接到另一台机器。
00:02:04可以是我的本地机器,
00:02:06或者是云端机器,
00:02:07然后在该机器内渲染一个假终端或伪终端,
00:02:10其尺寸与客户端的终端相同。
00:02:13所以如果我们输入按键,
00:02:14按键信息会被发送
00:02:16到另一台机器,
00:02:18该机器执行这些按键,
00:02:20渲染结果,
00:02:22并将所有信息
00:02:23并将所有这些信息传回客户端。
00:02:25这种往返交互必须
00:02:26非常快速且低延迟。
00:02:28所以连接客户端和
00:02:30另一台机器的最好方式
00:02:31就是使用 WebSockets。
00:02:32让我们这样做吧。
00:02:34我们可以使用我已经设置好的 Ubuntu 服务器
00:02:35并安装了 Node。
00:02:37我还准备了一个
00:02:38带有服务器脚本的 Wterm 服务器。
00:02:40如果我们看一下它,
00:02:42可以看到我们正在创建一个
00:02:43WebSocket 服务器,挂载在
00:02:45/api/terminal 路径下。
00:02:48这一点稍后会更清楚。
00:02:49往下看,
00:02:49我们正在生成一个伪终端,
00:02:51其名称与我们的终端类型匹配。
00:02:53如果你好奇,这是查看你自己的方式。
00:02:55这里,
00:02:56我们接收来自客户端的任何按键,
00:02:58在服务器上处理它,
00:02:59也就是在我们的假终端里,
00:03:01然后把信息返回给
00:03:02那边的客户端。
00:03:03所以服务器返回所有内容,
00:03:05而不只是更新的那一行。
00:03:07现在在客户端的 app.tsx 文件中,
00:03:10我们正在通过 WebSocket 连接
00:03:11到我们服务器的 /api/terminal 端口。
00:03:14然后我们使用 Wterm 的 WebSocket 转换
00:03:16来连接该 URL
00:03:19并实现自动重连。
00:03:21这会发送按键信息
00:03:23从这里发到服务器。
00:03:24我们在这里处理浏览器调整大小,
00:03:26然后往下,
00:03:27handleData 函数
00:03:28处理来自服务器的
00:03:30所有信息。
00:03:31ZIG 核心的酷之处在于
00:03:33它会解析这些信息,
00:03:35弄清楚发生了什么变化,
00:03:36并只重新渲染那部分的 HTML。
00:03:39在这里,列和行的大小
00:03:41需要与我们在服务器上的一致,
00:03:42其他一切都相当直观。
00:03:45所以现在客户端和服务器都运行起来了,
00:03:47回到浏览器,如果我输入 LS,
00:03:49我们可以看到它列出了我们可以使用的文件。
00:03:52所以我可以用 -l 标志执行 LS,
00:03:53来查看关于文件的更多信息。
00:03:55我可以 CD 进入一个文件,
00:03:57看看里面的信息,
00:03:59也可以做一些事情,比如查看
00:04:01我正在运行的容器列表。
00:04:02甚至可以用 Vim 打开文件
00:04:03并在其中导航。
00:04:04但尽管所有这些都能工作,
00:04:06效果并不是特别好。
00:04:07我是说,如果我们要高亮显示一些文本,
00:04:09可以看到一些字符
00:04:10完全不可读。
00:04:12为了修复它,
00:04:13我们可以通过加载 Ghosty 核心
00:04:15并将其作为 React 中的 prop 添加,
00:04:16来使用 Ghosty 配置 Wterm。
00:04:18现在可以看到,如果我们打开服务器文件
00:04:20并高亮显示一些文本,
00:04:22一切都清晰多了。
00:04:23它甚至能做些事情,
00:04:24比如正确渲染 OpenCode,
00:04:26允许我们切换模型,
00:04:27并提供带有 Emoji 支持的提示词。
00:04:29我们甚至可以看到 Ghosty 渲染颜色的效果
00:04:31比使用默认的
00:04:31Wterm 核心渲染器稍微好一点。
00:04:34但 Zig 核心只有 12KB,
00:04:36而 Ghosty 则有 400KB。
00:04:39所以如果你关心大小,
00:04:40那也许坚持使用 Zig 核心。
00:04:43总之,这是 Vercel 提供的 Wterm 的快速概览。
00:04:46当然,还有更多功能我没有介绍,
00:04:48比如能够将 Markdown
00:04:49转换为漂亮的终端输出,
00:04:51如果你无法访问后端,
00:04:52只需使用 Bash 在假文件之间导航。
00:04:55甚至还有关于如何通过
00:04:57浏览器中的终端
00:04:58设置 SSH 客户端的示例。
00:05:00但我并没有发现 Wterm 是完美的。
00:05:02使用 Ghosty 版本时存在一些渲染问题,
00:05:05特别是在 NeoVim
00:05:06甚至 OpenCode 之间来回切换时。
00:05:08为了让 Ghosty 渲染器在我的
00:05:10BUN 前端中工作,
00:05:11我必须显式导入 WASM 文件,
00:05:13因为 BUN 不会从
00:05:15Node modules 文件夹中复制任何非 JS 文件。
00:05:17但我确实喜欢 DOM 渲染方法,
00:05:19这意味着你可以获得辅助功能
00:05:21和原生的浏览器特性,
00:05:23而无需做任何额外工作,
00:05:25尽管 Xterm 努力了这么久,
00:05:27也依然难以做到。
00:05:29不过 Xterm.js 确实拥有庞大的生态系统,
00:05:31而且是经过实战检验的解决方案,
00:05:33所以选择它也不会出错。
00:05:35还有由 Coda 开发的 GhostyWeb,
00:05:38它采取了不同的方法。
00:05:40它使用了相同的 libGhosty 引擎,
00:05:42也就是实际的 Ghosty 终端使用的那个,
00:05:43但它是 Xterm 的直接替代品,
00:05:45所以它仍然使用 canvas 渲染方法
00:05:48并且使用相同的 API,
00:05:50但你确实能得到一个更好的终端。
00:05:52(抱歉,之前的索引有误,
00:05:54这最后一个索引是正确结尾。)
Community Posts
No posts yet. Be the first to write about this video!
Write about this video