wterm: Веб-терминал от Vercel на базе Ghostty

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

Transcript

00:00:00Это Wterm, веб-эмулятор терминала от Vasell,
00:00:03который рендерится прямо в DOM, а не в canvas.
00:00:06Поэтому выделение текста, поиск в браузере,
00:00:08и программы чтения с экрана отлично с ним работают.
00:00:10Он написан на Zig, компилируется в WASM-бинарник на 12 КБ,
00:00:14и также имеет опциональный бэкенд на базе LibGhosty,
00:00:17того же движка, на котором работает терминал Ghosty,
00:00:19что дает вам полную совместимость с терминалом в браузере.
00:00:22Но действительно ли WASM-бинарника на 12 КБ
00:00:24достаточно, чтобы заменить нативный эмулятор терминала?
00:00:28Вероятно, нет, но подпишитесь, и давайте выясним.
00:00:33Итак, веб-терминалы есть практически везде.
00:00:36В облачных IDE, таких как GitHub Codespaces,
00:00:39инструментах инфраструктуры, таких как Portainer или Qualify,
00:00:41и даже в настольных IDE, таких как VS Code или Cursor.
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 также может делать действительно крутые вещи
00:01:13с этим HTML-рендерингом,
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который заменяет вызов Zig на lib ghosty
00:01:29и работает на удивление лучше,
00:01:31чем другой веб-проект ghosty,
00:01:33о котором мы поговорим позже в видео.
00:01:35Но пока давайте попробуем Wterm
00:01:37на простом демо-проекте.
00:01:38Итак, после установки Wterm с React,
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Мы можем использовать HETS на сервере
00:02:35с Ubuntu, который я уже настроил
00:02:37с установленным Node.
00:02:38И у меня также уже есть сервер Wterm
00:02:40с серверным скриптом.
00:02:42Если мы заглянем внутрь,
00:02:43мы увидим, что создаем сервер WebSocket
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Затем мы используем трансформацию WebSocket
00:03:16из Wterm для подключения к этому URL
00:03:19с автоматическим переподключением.
00:03:21Затем это отправляет информацию о нажатиях клавиш
00:03:23отсюда на сервер.
00:03:24Мы обрабатываем изменение размера браузера здесь,
00:03:26а затем внизу,
00:03:27функция handle data
00:03:28обрабатывает всю информацию,
00:03:30которая поступает с сервера.
00:03:31И крутая вещь в ядре ZIG
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Так что я могу ввести LS с флагом L,
00:03:53чтобы увидеть больше информации о файлах.
00:03:55Я могу перейти в файл,
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мы можем настроить Wterm с Ghosty,
00:04:15загрузив ядро Ghosty
00:04:16и добавив его как проп в React.
00:04:18Вы можете увидеть теперь, что если мы откроем серверный файл
00:04:20и выделим текст,
00:04:22всё гораздо более читаемо.
00:04:23Он может даже делать такие вещи, как
00:04:24правильно отображать открытый код,
00:04:26позволяя нам менять модели,
00:04:27и давать ему промпт с поддержкой эмодзи.
00:04:29Мы даже видим, что Ghosty отображает цвета
00:04:31немного лучше,
00:04:31чем с рендерером ядра Wterm по умолчанию.
00:04:34Но ядро Zig весит всего 12 КБ
00:04:36по сравнению с 400 КБ от Ghosty.
00:04:39Так что если вас заботит размер,
00:04:40то, возможно, стоит придерживаться ядра Zig.
00:04:43В любом случае, это краткий обзор Wterm от Vercel.
00:04:46Конечно, есть еще так много функций,
00:04:48которые я не затронул,
00:04:49например, возможность конвертировать Markdown
00:04:51в красивый вывод терминала,
00:04:52использование просто Bash для навигации по фейковым файлам,
00:04:55если у вас нет доступа к бэкенду.
00:04:57И есть даже примеры
00:04:58того, как настроить SSH-клиент
00:05:00через терминал в браузере.
00:05:02Но я не нашел Wterm идеальным.
00:05:05Были некоторые проблемы с рендерингом,
00:05:06при использовании версии Ghosty,
00:05:08при переключении туда и обратно между NeoVim
00:05:10или даже OpenCode.
00:05:11И чтобы заставить рендерер Ghosty работать
00:05:13с моим фронтендом на BUN,
00:05:15мне пришлось импортировать файл WASM,
00:05:17потому что BUN не копировал никакие не-JS файлы
00:05:19из папки Node modules.
00:05:21Но мне нравится подход с рендерингом в DOM,
00:05:23что означает, что вы получаете доступность
00:05:25и нативные функции браузера
00:05:27без выполнения какой-либо дополнительной работы,
00:05:29с чем Xterm изо всех сил пытался справиться,
00:05:31несмотря на то, что он существует уже более 10 лет.
00:05:33Но у Xterm.js есть огромная экосистема
00:05:35и это проверенное в бою решение,
00:05:38так что вы не ошибетесь, если в итоге выберете его.
00:05:40Есть также GhostyWeb от Coda,
00:05:42который использует другой подход.
00:05:43Он использует тот же движок libGhosty,
00:05:45используемый настоящим терминалом Ghosty,
00:05:48но это прямая замена для Xterm,
00:05:50поэтому он всё ещё использует подход рендеринга canvas
00:05:52и использует тот же API,
00:05:54но вы получаете лучший терминал.

Key Takeaway

Wterm представляет собой легкий терминальный эмулятор, который заменяет canvas-рендеринг на DOM, предоставляя лучшую доступность и гибкость по сравнению со стандартом Xterm.js при весе бинарника всего 12 КБ.

Highlights

  • Wterm рендерит вывод терминала напрямую в DOM, обеспечивая нативную поддержку выделения текста, поиска в браузере и программ чтения с экрана.

  • Ядро Wterm на языке Zig весит всего 12 КБ, что значительно меньше 400 КБ, необходимых для использования движка Ghostty.

  • Интеграция с WebSocket позволяет клиенту Wterm обмениваться данными с удаленным псевдотерминалом в режиме реального времени.

  • Рендеринг в DOM позволяет перерисовывать только изменившиеся строки, а не весь экран терминала при каждом обновлении кадра.

  • Использование библиотеки libGhostty в составе Wterm улучшает читаемость текста и отображение цветов при работе с такими инструментами, как Neovim.

Timeline

Преимущества Wterm над Xterm.js

  • Wterm использует DOM вместо canvas для отображения вывода.
  • Архитектура на языке Zig обеспечивает компактный размер WASM-бинарника.
  • Доступ к нативным функциям браузера упрощает работу с текстом.

Большинство существующих веб-терминалов полагаются на Xterm.js, который использует canvas. Это создает сложности при реализации поиска по странице и выделении текста. Wterm решает эти проблемы, превращая вывод терминала в стандартные HTML-элементы, что делает его совместимым с инструментами доступности.

Настройка серверного взаимодействия

  • WebSockets обеспечивают обмен данными между клиентом и удаленным псевдотерминалом.
  • Сервер обрабатывает нажатия клавиш и возвращает обновленный вывод.
  • Оптимизированная перерисовка обновляет только измененные части DOM.

Для работы терминала требуется подключение к бэкенду, который запускает псевдотерминал с заданными параметрами размера. Нажатия клавиш передаются на сервер, обрабатываются, после чего результат отправляется обратно клиенту. Этот процесс обеспечивает высокую скорость работы и корректное взаимодействие с приложениями типа Vim.

Интеграция с Ghostty и ограничения

  • Подключение libGhostty повышает качество рендеринга цветов и символов.
  • Wterm с ядром Zig занимает меньше места, чем версия с Ghostty.
  • Xterm.js остается проверенным решением с обширной экосистемой.

Несмотря на преимущества DOM-рендеринга, некоторые символы могут отображаться некорректно без использования ядра Ghostty. Внедрение Ghostty требует большего размера WASM-файла, но улучшает визуальную составляющую. Выбор между Wterm и Xterm.js зависит от требований к доступности или необходимости использовать уже существующую широкую базу плагинов Xterm.js.

Community Posts

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

Write about this video