10 KiB
10 KiB
xterminal 与 wetty client 详细差异对比
1. 对比范围与结论
本文对比对象:
xterminal:/Users/gavin/lab/xterminalwetty当前项目前端 client:/Users/gavin/lab/wetty/src/client/wetty/**(以及其页面与配置面板)
核心结论:
- 两者不是同层替代关系。
xterminal是前端终端组件库,wetty client是完整 Web SSH 网关客户端。 wetty client的核心能力来自xterm.js真终端仿真;xterminal核心是“CLI 交互组件”,终端协议能力主要由业务层补齐。- 若目标是“做 SSH/PTY 级别会话”,
wetty client路线更直接;若目标是“嵌入式 Web CLI 组件”,xterminal更轻更可控。
2. 产品定位与边界
xterminal(组件库定位)
- 对外是
XTerminal类 API(mount/write/history/setCompleter/pause/resume/dispose)。 - 不绑定任何固定后端协议,网络连接由业务方自行实现。
- 证据:
source/index.ts:14(类定义)source/index.ts:95(挂载)source/index.ts:53(输出 API)source/index.ts:90(补全)
wetty client(业务客户端定位)
- 页面入口直接完成:终端初始化、断线重连 UI、网关连接、数据收发。
- 与运行配置、网关协议、页面 DOM 强耦合。
- 证据:
src/client/wetty.ts:26(启动终端)src/client/wetty.ts:38(socket 事件链)src/client/wetty/socket.ts:43(网关 socket 实现)
3. 渲染与终端仿真能力
wetty client:xterm.js 终端仿真
- 直接继承
@xterm/xterm的Terminal。 - 加载了
FitAddon、WebLinksAddon、ImageAddon。 - 原生具备终端仿真语义(光标、控制序列、窗口 resize、链接识别等)。
- 证据:
src/client/wetty/term.ts:13src/client/wetty/term.ts:21src/client/wetty/term.ts:23src/client/wetty/term.ts:24
xterminal:组件渲染模型
- 输出层以 HTML 片段写入为主。
- 核心库不自带完整 VT/ANSI 终端协议仿真。
- ANSI 处理与网关协议示例主要存在于 demo 脚本,不在库核心 API。
- 证据:
source/output/index.ts:40source/output/index.ts:49demo/main.js:381(ANSI 转换)
4. 输入模型差异(交互体验关键)
wetty client:按键流(streaming input)
- 用户每次按键通过
term.onData立即发送到后端。 - 更接近真实 SSH TTY 行为(如逐字符编辑、交互式全屏程序)。
- 证据:
src/client/wetty.ts:60
xterminal:行输入(line-based)
- 默认在
Enter时触发data事件并提交一整行。 - 上下箭头与历史命令是组件内建行为。
- 证据:
source/instance.ts:136(Enter 分支)source/instance.ts:141(emit data)source/instance.ts:147(历史导航)
影响:
- 需要 PTY 级“实时按键”时,
xterminal必须由业务层额外桥接按键事件。 - 需要“类 REPL 文本命令输入”时,
xterminal默认体验更简单。
5. 协议与连接层
wetty client:内置网关协议适配
- 内建
GatewaySocket,封装事件connect/login/data/logout/disconnect/error。 - 支持
init/stdin/resize/control帧。 - 自动处理
ping/pong、connected、disconnect控制帧。 - 证据:
src/client/wetty/socket.ts:3src/client/wetty/socket.ts:57src/client/wetty/socket.ts:103src/client/wetty/socket.ts:238
xterminal:协议在业务层(demo)实现
- 核心库无 WebSocket 协议绑定。
- demo 中手工实现网关连接、帧发送、回包处理、排队与批量 flush。
- 证据:
demo/main.js:635(connectByConfig)demo/main.js:572(handleGatewayFrame)demo/main.js:501(stdin 发送)
6. 配置系统与可配置能力
wetty client
- 运行时读取
/terminal.config.json,并做最小字段校验、选中 server 逻辑。 - 有 iframe 配置面板,可改大量 xterm 选项并持久化
localStorage.options。 - 证据:
src/client/wetty/runtimeConfig.ts:77src/client/wetty/runtimeConfig.ts:107src/client/wetty/term/confiruragtion.ts:8src/client/wetty/term/load.ts:10src/assets/xterm_config/index.html:62
xterminal
- 核心库配置简单(主要是挂载 target)。
- 无内建“终端参数 GUI 编辑器”,这部分由业务层自行实现。
- 证据:
source/types.d.ts:103
7. 移动端策略对比
wetty client
- 对 xterm 屏幕加
contenteditable以触发软键盘。 - 页面内置功能键浮层(方向键、Esc、Ctrl、Tab)。
- 证据:
src/client/wetty/mobile.ts:3index.html:28src/client/wetty/term.ts:190
xterminal
- 核心对移动端做了更系统处理:
- 隐藏 textarea + 自绘光标
visualViewport监听,动态补偿软键盘遮挡- 避免 iOS Safari 聚焦导致 body 整体上推
- 证据:
source/instance.ts:58source/renderer/index.ts:27theme/index.css:68
结论:
wetty的移动端更偏“终端页面增强”。xterminal的移动端更偏“组件内部自洽”。
8. 安全与风险点
8.1 前端渲染安全
-
xterminal提供writeSafe/escapeHTML,明确区分不可信文本输出路径。 -
证据:
source/index.ts:61source/output/index.ts:19
-
wetty断线信息使用innerHTML注入文本,若消息来源不可信有注入风险。 -
证据:
src/client/wetty/disconnect.ts:9
8.2 配置泄露风险
- 两边当前
terminal.config.json都包含明文密码,属于高风险配置习惯(即使是开发环境)。 - 证据:
/Users/gavin/lab/wetty/terminal.config.json/Users/gavin/lab/xterminal/terminal.config.json
9. 特性差异清单(功能维度)
wetty client 独有/更强
- xterm.js 终端仿真与 addon 生态。
- 现成文件下载控制序列解析(
ESC[5i/ESC[4i)。 - 完整连接态 UI(overlay、reconnect、配置侧栏)。
- 网关初始化载荷构造(含证书/私钥/密码多认证类型)。
证据:
src/client/wetty/download.ts:4src/client/wetty/download.ts:76src/client/wetty/socket.ts:161index.html:14
xterminal 独有/更强
- 组件化 API 清晰,易嵌入任意前端。
- 事件总线与资源释放边界明确(
dispose、register)。 - 历史记录与补全接口简洁。
- 测试覆盖相对更系统(input/output/history/emitter/xterminal)。
证据:
source/index.ts:117source/emitter/index.ts:16tests/xterminal.test.ts:4tests/input.test.ts:5
10. 工程化与依赖体量
依赖与发布目标
-
wetty:- 运行时依赖较重(含
@xterm/*、express、socket.io、node-pty等)。 - 发布目标是应用(
bin/main+ server + client)。 - 证据:
package.json:44(dependencies)
- 运行时依赖较重(含
-
xterminal:- 核心 runtime 无 dependencies(仅 devDependencies)。
- 发布目标是库(UMD + ESM + CSS + types)。
- 证据:
package.json:64(devDependencies)、rollup.config.js:31
产物规模(当前工作区构建结果)
wettyclient bundle:build/client/wetty.js约511K(含 source map 更大)。xterminaldist:xterminal.esm.js约8.5K,xterminal.umd.js约16K。
结论:
- 若只需要嵌入命令交互 UI,
xterminal体量优势明显。 - 若需要终端仿真,
wetty/xterm.js 的体量属于能力成本。
11. 测试对比
-
wetty当前仓库测试集中在:- 客户端
FileDownloader - 服务端 shell escaping
- 证据:
src/client/wetty/download.spec.ts:10、src/server/shared/shell.spec.ts:5
- 客户端
-
xterminal测试覆盖:xterminal/input/output/history/emitter/disposable/reactivity- 证据:
/Users/gavin/lab/xterminal/tests/*.test.ts
12. 当前项目内一个关键不一致点
在当前 wetty 仓库中,前端 client 已改为“网关 WebSocket 帧协议”,但后端原有代码仍是 Socket.IO 事件模型(input/resize/commit)。
- 前端证据:
src/client/wetty/socket.ts:97 - 后端证据:
src/server/spawn.ts:38、src/server/socketServer/socket.ts:38
这意味着:
- 当前 client 与本仓库原 server 不天然对接。
- client 实际更像在对接外部网关服务,而不是本地 wetty server。
13. 选型建议(按目标场景)
选 wetty client 路线
适合:
- 目标是“浏览器里完整 SSH 终端”。
- 需要 xterm.js 级别兼容能力(控制序列、终端行为一致性)。
- 接受更重依赖与更复杂调试链路。
选 xterminal 路线
适合:
- 目标是“可嵌入、可定制、轻量 CLI 组件”。
- 协议、渲染、会话行为希望完全可控。
- 可接受自行补齐 SSH/ANSI/PTY 的业务层逻辑。
14. 如果要做“xterminal + wetty 能力融合”,推荐最小改造路径
- 保持
xterminal作为 UI 输入输出壳,不直接替换为 xterm.js。 - 单独抽出
gateway client模块(connect/send/receive/reconnect),不要继续写在 demo/page 脚本。 - 定义统一帧协议适配层,把
init/stdin/resize/control/stdout/stderr/error规范化。 - 将 ANSI 渲染器从 demo 抽为独立模块,补测试(尤其是跨帧、退格、CR/LF)。
- 最后再评估是否有必要迁移到 xterm.js(仅在终端兼容性成为瓶颈时)。
15. 风险清单(落地前需确认)
- 明文密码配置必须替换(令牌化或后端临时凭据)。
- 断线错误信息渲染方式应改为安全文本输出(避免
innerHTML注入)。 - 若要支持交互式全屏程序(vim/top/tmux),需确认输入模型是按键流而非行输入。
- 若继续沿用移动端触控条,需要统一“焦点不丢失”的处理策略(当前两项目实现不同)。
16. 快速摘要(一页版)
xterminal是“轻量终端 UI 组件库”;wetty client是“完整 Web SSH 客户端”。wetty的强项是 xterm.js 终端仿真;xterminal的强项是组件化、轻量、可嵌入。- 两者可融合,但不是无缝替换;最大差异在输入模型、协议耦合、终端仿真深度。
- 当前
wetty仓库里 client/server 协议模型存在分叉,后续演进需先统一架构方向。