wterm: O terminal web da Vercel impulsionado pelo Ghostty

BBetter Stack
컴퓨터/소프트웨어AI/미래기술

Transcript

00:00:00Este é o Wterm, um emulador de terminal baseado na web da Vasell
00:00:03que renderiza diretamente no DOM em vez de em um canvas.
00:00:06Portanto, seleção de texto, busca no navegador,
00:00:08e leitores de tela simplesmente funcionam com ele.
00:00:10Ele é escrito em Zig, compila para um binário WASM de 12 kilobytes,
00:00:14e há também um backend opcional alimentado pela LibGhosty,
00:00:17o mesmo mecanismo que alimenta o terminal Ghosty,
00:00:19o que lhe dá total compatibilidade de terminal no navegador.
00:00:22Mas será que um binário WASM de 12 kilobytes
00:00:24é realmente suficiente para substituir um emulador de terminal nativo?
00:00:28Provavelmente não, mas inscreva-se e vamos descobrir.
00:00:33Então, terminais web estão praticamente em toda parte.
00:00:36Em IDEs na nuvem como o GitHub Codespaces,
00:00:39ferramentas de infraestrutura como Portainer ou Qualify,
00:00:41e até IDEs desktop como VS Code ou Cursor.
00:00:44Mas todos eles usam o Xterm.js para isso,
00:00:47porque ele existe há muito tempo
00:00:49e é basicamente o padrão.
00:00:51O Xterm tem um grande problema, no entanto.
00:00:52Ele renderiza para um elemento canvas.
00:00:54Então, fazer coisas como selecionar texto
00:00:56ou encontrar palavras em uma página
00:00:58precisam ser reimplementadas do zero,
00:01:00o que nem sempre funciona muito bem.
00:01:02O Wterm adota uma abordagem completamente diferente
00:01:04ao renderizar para o DOM,
00:01:05o que significa que a saída do terminal é apenas HTML,
00:01:08e o navegador basicamente lida com isso de graça.
00:01:10Mas o Wterm também pode fazer algumas coisas realmente legais
00:01:13com essa renderização HTML,
00:01:14como apenas renderizar novamente a linha que foi atualizada,
00:01:17em vez de renderizar todo o terminal em cada quadro.
00:01:20Ele também pode ser escrito em diferentes frameworks
00:01:22como React ou Vue.
00:01:23Você pode mudar o tema.
00:01:24E também existe um pacote Wterm ghosty separado,
00:01:27que troca a chamada zig pela lib ghosty
00:01:29e funciona surpreendentemente melhor
00:01:31do que o outro projeto web ghosty,
00:01:33sobre o qual falaremos mais tarde no vídeo.
00:01:35Mas por enquanto, vamos testar o Wterm
00:01:37com um projeto de demonstração simples.
00:01:38Então, após instalar o Wterm com React,
00:01:40importei o componente, bem como o CSS,
00:01:43e estou renderizando o componente aqui.
00:01:45Então, se eu rodar o app e for ao navegador,
00:01:48posso ver que há um terminal.
00:01:49Mas se eu digitar um comando como ls,
00:01:51podemos ver que nada acontece.
00:01:52E isso é porque ele não está conectado
00:01:53a outro computador para ler informações.
00:01:56Deixe-me explicar.
00:01:57Então, agora o cliente não está conectado a um backend,
00:01:59então não há lugar de onde obter informações.
00:02:01Mas o que precisamos fazer é conectá-lo a outra máquina.
00:02:04Pode ser minha máquina local
00:02:06ou uma máquina na nuvem,
00:02:07e então renderizar um terminal falso ou um pseudo terminal
00:02:10dentro dessa máquina com as mesmas dimensões
00:02:13daquela do cliente.
00:02:14Então, se fizermos algumas teclas,
00:02:16essas informações de teclas são enviadas
00:02:18para a outra máquina,
00:02:20que executa essas teclas,
00:02:22renderiza os resultados,
00:02:23e envia todas essas informações de volta ao cliente.
00:02:25E esse vai e vem precisa acontecer
00:02:26muito rapidamente com atraso mínimo.
00:02:28Então a melhor maneira de conectar o cliente
00:02:30e a outra máquina juntos
00:02:31é usar WebSockets.
00:02:32Então vamos fazer isso.
00:02:34Podemos usar um HETS no servidor
00:02:35com Ubuntu que já configurei
00:02:37com Node instalado.
00:02:38E eu também já tenho um servidor Wterm
00:02:40com um script de servidor.
00:02:42Então, se olharmos para isso,
00:02:43podemos ver que estamos criando um servidor WebSocket
00:02:45no caminho slash API terminal.
00:02:48Isso fará mais sentido um pouco mais tarde.
00:02:49E aqui embaixo,
00:02:49estamos gerando um pseudo terminal
00:02:51com um nome que corresponde ao nosso tipo de terminal.
00:02:53Veja como você pode encontrar o seu se estiver curioso.
00:02:55E aqui embaixo,
00:02:56estamos recebendo qualquer tecla do cliente,
00:02:58processando-a no servidor,
00:02:59então dentro do nosso terminal falso,
00:03:01e então retornando essas informações
00:03:02para o cliente aqui.
00:03:03Portanto, o servidor retorna tudo
00:03:05e não apenas uma linha específica que foi atualizada.
00:03:07Agora, no cliente, no arquivo app.tsx,
00:03:10estamos fazendo uma conexão WebSocket
00:03:11para o nosso servidor na porta slash API slash terminal.
00:03:14Então estamos usando a transformação WebSocket
00:03:16do Wterm para conectar a essa URL
00:03:19com reconexões automáticas.
00:03:21Então é isso que envia informações de teclas
00:03:23daqui para o servidor.
00:03:24Lidamos com o redimensionamento do navegador aqui,
00:03:26e então aqui embaixo,
00:03:27e a função handle data
00:03:28lida com todas as informações
00:03:30que vêm do servidor.
00:03:31E a coisa legal sobre o núcleo ZIG
00:03:33é que ele vai passar essas informações,
00:03:35descobre o que mudou,
00:03:36e renderiza apenas essa parte do HTML.
00:03:39Aqui embaixo, o tamanho da coluna e da linha
00:03:41precisam corresponder ao que tínhamos no servidor,
00:03:42e todo o resto é bastante autoexplicativo.
00:03:45Então, com o cliente e o servidor rodando,
00:03:47de volta ao navegador, se eu digitar LS,
00:03:49podemos ver que ele lista os arquivos que temos disponíveis.
00:03:52Então eu poderia digitar LS com a flag L
00:03:53para ver mais informações sobre os arquivos.
00:03:55Posso entrar em um arquivo,
00:03:57dar uma olhada nas informações dentro dele,
00:03:59e também fazer coisas como ver a lista
00:04:01de contêineres que tenho rodando.
00:04:02Posso até abrir um arquivo com Vim
00:04:03e navegar por ele.
00:04:04Mas mesmo que tudo isso funcione,
00:04:06não funciona de forma incrível.
00:04:07Quero dizer, se tentarmos destacar algum texto,
00:04:09podemos ver que alguns caracteres
00:04:10são completamente ilegíveis.
00:04:12Então, para corrigir isso,
00:04:13podemos configurar o Wterm com Ghosty
00:04:15carregando o núcleo Ghosty
00:04:16e adicionando-o como uma prop no React.
00:04:18Você pode ver agora que se abrirmos o arquivo do servidor
00:04:20e destacarmos algum texto,
00:04:22tudo fica muito mais legível.
00:04:23Ele pode até fazer coisas como
00:04:24renderizar o código aberto corretamente,
00:04:26nos permitindo mudar de modelo,
00:04:27e dar um prompt com suporte a emoji.
00:04:29Podemos até ver que o Ghosty renderiza cores
00:04:31ligeiramente melhor
00:04:31do que com o renderizador de núcleo Wterm padrão.
00:04:34Mas o núcleo Zig tem apenas 12 kilobytes
00:04:36em comparação com os 400 kilobytes do Ghosty.
00:04:39Então, se você se preocupa com o tamanho,
00:04:40talvez fique com o núcleo Zig.
00:04:43De qualquer forma, essa é uma visão geral rápida do Wterm da Vercel.
00:04:46Claro, há muito mais recursos
00:04:48que não mencionei,
00:04:49como poder converter Markdown
00:04:51em uma boa saída de terminal,
00:04:52usar apenas Bash para navegar por arquivos falsos
00:04:55se você não tiver acesso a um backend.
00:04:57E há até exemplos
00:04:58de como configurar um cliente SSH
00:05:00através de um terminal no navegador.
00:05:02Mas não achei o Wterm perfeito.
00:05:05Houve alguns problemas de renderização
00:05:06ao usar a versão Ghosty,
00:05:08indo e voltando entre NeoVim
00:05:10ou mesmo OpenCode.
00:05:11E para fazer o renderizador Ghosty funcionar
00:05:13com meu frontend BUN,
00:05:15tive que importar o arquivo WASM
00:05:17porque o BUN não copiava nenhum arquivo não JS
00:05:19da pasta de módulos do Node.
00:05:21Mas gosto da abordagem de renderização DOM,
00:05:23o que significa que você obtém acessibilidade
00:05:25e recursos nativos do navegador
00:05:27sem fazer nenhum trabalho extra,
00:05:29o que o Xterm tem lutado para fazer,
00:05:31mesmo existindo há mais de 10 anos.
00:05:33Mas o Xterm.js tem um ecossistema enorme
00:05:35e é a solução testada em batalha,
00:05:38então você não errará se acabar escolhendo-o.
00:05:40Há também o GhostyWeb da Coda,
00:05:42que adota uma abordagem diferente.
00:05:43Ele usa o mesmo mecanismo libGhosty
00:05:45usado pelo terminal Ghosty real,
00:05:48mas é um substituto direto para o Xterm,
00:05:50então ele ainda usa a abordagem de renderização canvas
00:05:52e usa a mesma API,
00:05:54mas você obtém um terminal melhor.

Key Takeaway

O Wterm oferece uma alternativa eficiente ao Xterm.js ao utilizar renderização baseada em DOM para garantir acessibilidade nativa, com um núcleo em Zig de 12 kilobytes ou suporte opcional à libGhosty para maior fidelidade visual.

Highlights

  • O Wterm renderiza terminais via DOM em vez de canvas, permitindo suporte nativo a seleção de texto, busca e leitores de tela.

  • O núcleo padrão do Wterm, escrito em Zig, compila para um binário WASM de apenas 12 kilobytes.

  • A integração opcional com a libGhosty eleva o consumo de memória para 400 kilobytes, mas melhora a renderização de cores, emojis e legibilidade de textos selecionados.

  • A comunicação entre o cliente Wterm e o backend é realizada via WebSockets, enviando entradas de teclado e recebendo renderizações de saída.

  • O Wterm atualiza apenas a linha alterada no navegador, contrastando com o Xterm.js que renderiza o terminal inteiro em cada quadro.

Timeline

Arquitetura e diferenciais técnicos do Wterm

  • O Wterm utiliza o DOM para renderização em vez do elemento canvas tradicional.
  • O projeto é escrito em Zig e gera um binário WASM de 12 kilobytes.
  • A libGhosty pode ser usada como backend opcional para maior compatibilidade de terminal.

A maioria dos emuladores de terminal baseados na web, como os presentes no VS Code ou GitHub Codespaces, utiliza Xterm.js com renderização via canvas. O Wterm altera essa lógica ao renderizar em elementos DOM, possibilitando que o navegador gerencie nativamente a seleção de texto e busca. Além da leveza do núcleo em Zig, a capacidade de atualizar apenas linhas específicas em vez de todo o frame reduz o processamento.

Configuração de comunicação servidor-cliente

  • A conexão entre o cliente web e a máquina remota ocorre via WebSockets.
  • O servidor gera um pseudo terminal que reflete as dimensões do cliente.
  • As entradas do usuário são processadas no servidor e o resultado é enviado de volta ao cliente.

Para funcionar corretamente, o cliente precisa de um backend que processe os comandos. O processo envolve a criação de um servidor WebSocket que gerencia um pseudo terminal no host. O cliente envia os eventos de teclado, e o servidor retorna a saída processada, exigindo baixa latência para uma experiência fluida. O exemplo prático utiliza um servidor Ubuntu com Node.js para essa ponte.

Limitações e comparação com alternativas

  • A versão padrão com núcleo Zig pode apresentar problemas de legibilidade em seleções de texto.
  • A integração com a libGhosty resolve problemas de renderização e cores, apesar de aumentar o binário para 400 kilobytes.
  • O Xterm.js permanece como a opção testada em batalha com ecossistema mais vasto.

Embora o Wterm ofereça vantagens em acessibilidade via DOM, ele não é isento de falhas, apresentando inconsistências de renderização em editores como NeoVim. O GhostyWeb surge como outra alternativa que, embora mantenha a renderização por canvas, utiliza a mesma libGhosty para entregar uma emulação mais fiel. A escolha entre eles depende da necessidade de reduzir o tamanho do pacote ou de obter a máxima fidelidade na exibição de cores e caracteres.

Community Posts

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

Write about this video