wterm: La terminal web impulsada por Ghostty de Vercel

BBetter Stack
Computing/SoftwareInternet Technology

Transcript

00:00:00Este es Wterm, un emulador de terminal basado en web de Vercel
00:00:03que renderiza directamente en el DOM en lugar de en un canvas.
00:00:06Así que la selección de texto, buscar en el navegador,
00:00:08y los lectores de pantalla funcionan perfectamente con él.
00:00:10Está escrito en Zig, compila a un binario WASM de 12 kilobytes,
00:00:14y también tiene un backend opcional impulsado por LibGhosty,
00:00:17el mismo motor que impulsa la terminal Ghosty,
00:00:19lo que te da compatibilidad total con terminales en el navegador.
00:00:22Pero, ¿es un binario WASM de 12 kilobytes
00:00:24realmente suficiente para reemplazar un emulador de terminal nativo?
00:00:28Probablemente no, pero suscríbete y vamos a descubrirlo.
00:00:33Las terminales web están prácticamente en todas partes.
00:00:36En IDEs en la nube como GitHub Codespaces,
00:00:39herramientas de infraestructura como Portainer o Qualify,
00:00:41e incluso IDEs de escritorio como VS Code o Cursor.
00:00:44Pero todas usan Xterm.js para hacerlo
00:00:47porque ha existido durante mucho tiempo
00:00:49y es básicamente el estándar.
00:00:51Sin embargo, Xterm tiene un gran problema.
00:00:52Renderiza en un elemento canvas.
00:00:54Así que cosas como seleccionar texto
00:00:56o encontrar palabras en una página
00:00:58tienen que ser reimplementadas desde cero,
00:01:00lo cual no siempre funciona muy bien.
00:01:02Wterm toma un enfoque completamente diferente
00:01:04renderizando en el DOM,
00:01:05lo que significa que la salida de la terminal es solo HTML,
00:01:08y el navegador básicamente maneja eso gratis.
00:01:10Pero Wterm también puede hacer cosas realmente geniales
00:01:13con este renderizado HTML,
00:01:14como solo volver a renderizar la fila que se ha actualizado,
00:01:17en lugar de renderizar toda la terminal en cada frame.
00:01:20También se puede escribir en diferentes frameworks
00:01:22como React o Vue.
00:01:23Puedes cambiar el tema.
00:01:24Y también hay un paquete Wterm ghosty separado,
00:01:27que intercambia la llamada de Zig con lib ghosty
00:01:29y funciona sorprendentemente mejor
00:01:31que el otro proyecto web ghosty,
00:01:33del que hablaremos más adelante en el video.
00:01:35Pero por ahora, probemos Wterm
00:01:37con un proyecto de demostración simple.
00:01:38Después de instalar Wterm con React,
00:01:40he importado el componente así como el CSS,
00:01:43y estoy renderizando el componente aquí.
00:01:45Así que ahora, si ejecuto la aplicación y voy al navegador,
00:01:48puedo ver que hay una terminal.
00:01:49Pero si presiono un comando como ls,
00:01:51podemos ver que no pasa nada.
00:01:52Y esto es porque no está conectada
00:01:53a otra computadora para leer información.
00:01:56Déjame explicar.
00:01:57Ahora mismo el cliente no está conectado a un backend,
00:01:59así que no hay de dónde obtener información.
00:02:01Pero lo que tenemos que hacer es conectarlo a otra máquina.
00:02:04Puede ser mi máquina local
00:02:06o una máquina en la nube,
00:02:07y luego renderizar una terminal falsa o pseudo terminal
00:02:10dentro de esa máquina con las mismas dimensiones
00:02:13que la del cliente.
00:02:14Entonces, si hacemos algunas pulsaciones de teclas,
00:02:16esa información se envía
00:02:18a la otra máquina,
00:02:20que ejecuta esas pulsaciones,
00:02:22renderiza los resultados,
00:02:23y envía toda esa información de vuelta al cliente.
00:02:25Y ese ida y vuelta debe suceder
00:02:26muy rápidamente con un retraso mínimo.
00:02:28Así que la mejor manera de conectar el cliente
00:02:30y la otra máquina
00:02:31es usar WebSockets.
00:02:32Así que vamos a hacerlo.
00:02:34Podemos usar HETS en el servidor
00:02:35con Ubuntu que ya tengo configurado
00:02:37con Node instalado.
00:02:38Y también tengo un servidor Wterm
00:02:40con un script de servidor.
00:02:42Así que si miramos eso,
00:02:43podemos ver que estamos creando un servidor WebSocket
00:02:45en la ruta slash API terminal path.
00:02:48Esto tendrá más sentido un poco más adelante.
00:02:49Y aquí abajo,
00:02:49estamos generando una pseudo terminal
00:02:51con un nombre que coincide con nuestro tipo de terminal.
00:02:53Aquí es cómo puedes encontrar la tuya si tienes curiosidad.
00:02:55Y aquí abajo,
00:02:56obtenemos cualquier pulsación de tecla del cliente,
00:02:58procesándola en el servidor,
00:02:59es decir, dentro de nuestra terminal falsa,
00:03:01y luego devolviendo esa información
00:03:02al cliente aquí.
00:03:03Así que el servidor devuelve todo
00:03:05y no solo una fila específica que se ha actualizado.
00:03:07Ahora, en el cliente en el archivo app.tsx,
00:03:10estamos haciendo una conexión WebSocket
00:03:11a nuestro servidor en el puerto slash API slash terminal.
00:03:14Luego estamos usando la transformación WebSocket
00:03:16de Wterm para conectarnos a esa URL
00:03:19con reconexiones automáticas.
00:03:21Luego, esto es lo que envía información de pulsaciones
00:03:23desde aquí al servidor.
00:03:24Manejamos el cambio de tamaño del navegador aquí,
00:03:26y luego aquí abajo,
00:03:27la función handle data
00:03:28maneja toda la información
00:03:30que viene del servidor.
00:03:31Y lo genial del núcleo ZIG
00:03:33es que pasará esta información,
00:03:35averigua qué ha cambiado,
00:03:36y solo vuelve a renderizar esa parte del HTML.
00:03:39Aquí abajo, el tamaño de columna y fila
00:03:41deben coincidir con lo que teníamos en el servidor,
00:03:42y todo lo demás es bastante autoexplicativo.
00:03:45Así que ahora con el cliente y el servidor ejecutándose,
00:03:47de vuelta en el navegador, si presiono LS,
00:03:49podemos ver que enumera los archivos que tenemos disponibles.
00:03:52Así que podría presionar LS con el flag L
00:03:53para ver más información sobre los archivos.
00:03:55Puedo hacer CD en un archivo,
00:03:57echar un vistazo a la información dentro de él,
00:03:59y también hacer cosas como ver la lista
00:04:01de contenedores que tengo ejecutándose.
00:04:02Incluso puedo abrir un archivo con Vim
00:04:03y navegar a través de él.
00:04:04Pero aunque todo eso funciona,
00:04:06no lo hace increíblemente bien.
00:04:07Quiero decir, si intentamos resaltar algo de texto,
00:04:09podemos ver que algunos caracteres
00:04:10son completamente ilegibles.
00:04:12Así que para arreglar eso,
00:04:13podemos configurar Wterm con Ghosty
00:04:15cargando el núcleo de Ghosty
00:04:16y añadiéndolo como prop en React.
00:04:18Puedes ver ahora que si abrimos el archivo del servidor
00:04:20y resaltamos algo de texto,
00:04:22todo es mucho más legible.
00:04:23Incluso puede hacer cosas como
00:04:24renderizar código abierto correctamente,
00:04:26permitiéndonos cambiar de modelos,
00:04:27y darle un prompt con soporte para emojis.
00:04:29Incluso podemos ver que Ghosty renderiza los colores
00:04:31ligeramente mejor
00:04:31que con el renderizador central predeterminado de Wterm.
00:04:34Pero el núcleo Zig solo tiene 12 kilobytes
00:04:36en comparación con los 400 kilobytes de Ghosty.
00:04:39Así que si te importa el tamaño,
00:04:40entonces tal vez quédate con el núcleo Zig.
00:04:43De todos modos, ese es un resumen rápido de Wterm de Vercel.
00:04:46Por supuesto, hay muchas más características
00:04:48que no revisé,
00:04:49como poder convertir Markdown
00:04:51en una salida de terminal agradable,
00:04:52usando solo Bash para navegar a través de archivos falsos
00:04:55si no tienes acceso a un backend.
00:04:57E incluso hay ejemplos
00:04:58de cómo configurar un cliente SSH
00:05:00a través de una terminal en el navegador.
00:05:02Pero no me pareció que Wterm fuera perfecto.
00:05:05Hubo algunos problemas de renderizado
00:05:06al usar la versión Ghosty,
00:05:08yendo y viniendo entre NeoVim
00:05:10o incluso OpenCode.
00:05:11Y para conseguir que el renderizador Ghosty funcione
00:05:13con mi frontend de BUN,
00:05:15tuve que importar el archivo WASM
00:05:17porque BUN no copiaba ningún archivo que no fuera JS
00:05:19de la carpeta de módulos de Node.
00:05:21Pero me gusta el enfoque de renderizado DOM,
00:05:23lo que significa que obtienes accesibilidad
00:05:25y funciones nativas del navegador
00:05:27sin hacer ningún trabajo adicional,
00:05:29algo con lo que Xterm ha luchado,
00:05:31aunque ha existido durante más de 10 años.
00:05:33Pero Xterm.js tiene un ecosistema enorme
00:05:35y es la solución probada en batalla,
00:05:38así que no te equivocarás si terminas eligiéndolo.
00:05:40También está GhostyWeb de Coda,
00:05:42que toma un enfoque diferente.
00:05:43Utiliza el mismo motor libGhosty
00:05:45utilizado por la terminal Ghosty real,
00:05:48pero es un reemplazo directo para Xterm,
00:05:50por lo que todavía usa el enfoque de renderizado canvas
00:05:52y usa la misma API,
00:05:54pero obtienes una mejor terminal.

Key Takeaway

Wterm ofrece una alternativa a Xterm.js basada en el DOM que permite una integración nativa en el navegador y una renderización eficiente al actualizar solo las filas modificadas mediante un núcleo en Zig de 12 kilobytes.

Highlights

  • Wterm utiliza renderizado basado en DOM en lugar de elementos canvas para mejorar la compatibilidad con lectores de pantalla, la búsqueda nativa del navegador y la selección de texto.

  • El núcleo de Wterm está escrito en Zig y compila a un binario WebAssembly de solo 12 kilobytes.

  • Wterm optimiza el rendimiento al renderizar únicamente la fila específica que cambia, en lugar de redibujar toda la terminal en cada frame.

  • La integración opcional con libGhostty permite una compatibilidad de terminal superior y un mejor renderizado de colores, aunque aumenta el tamaño del binario a 400 kilobytes.

  • La comunicación entre el cliente Wterm y la máquina remota se realiza mediante WebSockets para minimizar la latencia en el envío de pulsaciones de teclas y la recepción de resultados.

Timeline

Arquitectura y ventajas de Wterm frente a Xterm.js

  • Wterm renderiza la salida de la terminal directamente en el DOM, permitiendo al navegador gestionar funciones como selección de texto y búsqueda.
  • Xterm.js depende de elementos canvas, lo que complica la reimplementación de funcionalidades estándar de navegación y accesibilidad.
  • El motor de Wterm utiliza un núcleo escrito en Zig que ocupa 12 kilobytes, con una opción de backend basada en libGhostty para mayor compatibilidad.

La mayoría de las terminales web como las de GitHub Codespaces o VS Code utilizan Xterm.js, lo que obliga a reimplementar funciones básicas del navegador sobre un canvas. Wterm rompe esta tendencia al tratar la salida de la terminal como HTML, logrando que el navegador maneje nativamente la interacción. Además, su arquitectura permite actualizaciones de renderizado más inteligentes al procesar solo los cambios fila por fila.

Implementación técnica y conexión mediante WebSockets

  • El cliente Wterm requiere una conexión a un backend o máquina remota para procesar comandos a través de una pseudo terminal.
  • Los WebSockets facilitan el intercambio de datos entre el navegador y el servidor, enviando pulsaciones de teclas y recibiendo el resultado del proceso.
  • El servidor genera una pseudo terminal con dimensiones sincronizadas con el cliente para asegurar una visualización coherente.

Para que la terminal sea funcional, Wterm debe conectarse a un servidor que ejecute los comandos. En el caso expuesto, se utiliza un servidor WebSocket que escucha en una ruta específica, captura los eventos de teclado del cliente, los ejecuta en una pseudo terminal y devuelve la salida al navegador. El componente de React de Wterm gestiona la reconexión automática y el redibujado selectivo basado en el núcleo de Zig.

Configuración de Ghostty y consideraciones de uso

  • La integración de libGhostty corrige problemas de legibilidad de caracteres y mejora el soporte de colores y emojis.
  • El núcleo de Ghostty tiene un peso de 400 kilobytes, significativamente mayor que los 12 kilobytes del núcleo estándar en Zig.
  • Wterm admite casos de uso como clientes SSH en el navegador y conversión de Markdown, aunque presenta retos de configuración en entornos como BUN.

Si bien Wterm es capaz de ejecutar comandos básicos, la integración con libGhostty es necesaria para una experiencia más refinada, especialmente al trabajar con herramientas como NeoVim. A pesar de los beneficios en accesibilidad del renderizado DOM, Xterm.js sigue siendo el estándar probado en batalla debido a su ecosistema masivo, mientras que alternativas como GhosttyWeb mantienen el modelo canvas pero mejoran la fidelidad de la terminal.

Community Posts

No posts yet. Be the first to write about this video!

Write about this video