# xterminal 与 wetty client 详细差异对比 ## 1. 对比范围与结论 本文对比对象: - `xterminal`:`/Users/gavin/lab/xterminal` - `wetty` 当前项目前端 client:`/Users/gavin/lab/wetty/src/client/wetty/**`(以及其页面与配置面板) 核心结论: 1. 两者不是同层替代关系。`xterminal` 是前端终端组件库,`wetty client` 是完整 Web SSH 网关客户端。 2. `wetty client` 的核心能力来自 `xterm.js` 真终端仿真;`xterminal` 核心是“CLI 交互组件”,终端协议能力主要由业务层补齐。 3. 若目标是“做 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:13` - `src/client/wetty/term.ts:21` - `src/client/wetty/term.ts:23` - `src/client/wetty/term.ts:24` ### xterminal:组件渲染模型 - 输出层以 HTML 片段写入为主。 - 核心库不自带完整 VT/ANSI 终端协议仿真。 - ANSI 处理与网关协议示例主要存在于 demo 脚本,不在库核心 API。 - 证据: - `source/output/index.ts:40` - `source/output/index.ts:49` - `demo/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`(历史导航) 影响: 1. 需要 PTY 级“实时按键”时,`xterminal` 必须由业务层额外桥接按键事件。 2. 需要“类 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:3` - `src/client/wetty/socket.ts:57` - `src/client/wetty/socket.ts:103` - `src/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:77` - `src/client/wetty/runtimeConfig.ts:107` - `src/client/wetty/term/confiruragtion.ts:8` - `src/client/wetty/term/load.ts:10` - `src/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:3` - `index.html:28` - `src/client/wetty/term.ts:190` ### xterminal - 核心对移动端做了更系统处理: - 隐藏 textarea + 自绘光标 - `visualViewport` 监听,动态补偿软键盘遮挡 - 避免 iOS Safari 聚焦导致 body 整体上推 - 证据: - `source/instance.ts:58` - `source/renderer/index.ts:27` - `theme/index.css:68` 结论: 1. `wetty` 的移动端更偏“终端页面增强”。 2. `xterminal` 的移动端更偏“组件内部自洽”。 --- ## 8. 安全与风险点 ### 8.1 前端渲染安全 - `xterminal` 提供 `writeSafe/escapeHTML`,明确区分不可信文本输出路径。 - 证据: - `source/index.ts:61` - `source/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 独有/更强 1. xterm.js 终端仿真与 addon 生态。 2. 现成文件下载控制序列解析(`ESC[5i` / `ESC[4i`)。 3. 完整连接态 UI(overlay、reconnect、配置侧栏)。 4. 网关初始化载荷构造(含证书/私钥/密码多认证类型)。 证据: - `src/client/wetty/download.ts:4` - `src/client/wetty/download.ts:76` - `src/client/wetty/socket.ts:161` - `index.html:14` ### xterminal 独有/更强 1. 组件化 API 清晰,易嵌入任意前端。 2. 事件总线与资源释放边界明确(`dispose`、`register`)。 3. 历史记录与补全接口简洁。 4. 测试覆盖相对更系统(input/output/history/emitter/xterminal)。 证据: - `source/index.ts:117` - `source/emitter/index.ts:16` - `tests/xterminal.test.ts:4` - `tests/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` ### 产物规模(当前工作区构建结果) - `wetty` client bundle:`build/client/wetty.js` 约 `511K`(含 source map 更大)。 - `xterminal` dist:`xterminal.esm.js` 约 `8.5K`,`xterminal.umd.js` 约 `16K`。 结论: 1. 若只需要嵌入命令交互 UI,`xterminal` 体量优势明显。 2. 若需要终端仿真,`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` 这意味着: 1. 当前 client 与本仓库原 server 不天然对接。 2. client 实际更像在对接外部网关服务,而不是本地 wetty server。 --- ## 13. 选型建议(按目标场景) ### 选 wetty client 路线 适合: 1. 目标是“浏览器里完整 SSH 终端”。 2. 需要 xterm.js 级别兼容能力(控制序列、终端行为一致性)。 3. 接受更重依赖与更复杂调试链路。 ### 选 xterminal 路线 适合: 1. 目标是“可嵌入、可定制、轻量 CLI 组件”。 2. 协议、渲染、会话行为希望完全可控。 3. 可接受自行补齐 SSH/ANSI/PTY 的业务层逻辑。 --- ## 14. 如果要做“xterminal + wetty 能力融合”,推荐最小改造路径 1. 保持 `xterminal` 作为 UI 输入输出壳,不直接替换为 xterm.js。 2. 单独抽出 `gateway client` 模块(`connect/send/receive/reconnect`),不要继续写在 demo/page 脚本。 3. 定义统一帧协议适配层,把 `init/stdin/resize/control/stdout/stderr/error` 规范化。 4. 将 ANSI 渲染器从 demo 抽为独立模块,补测试(尤其是跨帧、退格、CR/LF)。 5. 最后再评估是否有必要迁移到 xterm.js(仅在终端兼容性成为瓶颈时)。 --- ## 15. 风险清单(落地前需确认) 1. 明文密码配置必须替换(令牌化或后端临时凭据)。 2. 断线错误信息渲染方式应改为安全文本输出(避免 `innerHTML` 注入)。 3. 若要支持交互式全屏程序(vim/top/tmux),需确认输入模型是按键流而非行输入。 4. 若继续沿用移动端触控条,需要统一“焦点不丢失”的处理策略(当前两项目实现不同)。 --- ## 16. 快速摘要(一页版) 1. `xterminal` 是“轻量终端 UI 组件库”;`wetty client` 是“完整 Web SSH 客户端”。 2. `wetty` 的强项是 xterm.js 终端仿真;`xterminal` 的强项是组件化、轻量、可嵌入。 3. 两者可融合,但不是无缝替换;最大差异在输入模型、协议耦合、终端仿真深度。 4. 当前 `wetty` 仓库里 client/server 协议模型存在分叉,后续演进需先统一架构方向。