OpenTUI: создание терминальных приложений с помощью React, Bun и Zig

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

Transcript

00:00:00Это OpenTui, библиотека на Zig для создания терминальных интерфейсов с привязками
00:00:04для React, Solid и FreeJS, позволяющая создавать производительные TUI так же, как веб-
00:00:09приложения. Она была создана командой Anomaly, разработчиками популярного опенсорсного
00:00:14агента для кодинга OpenCode, чтобы обеспечить работу пользовательского интерфейса,
00:00:19которым пользуются миллионы людей на регулярной основе. Но как эта новая библиотека
00:00:24сравнится с другим популярным инструментом для создания терминальных интерфейсов на React,
00:00:29который существует гораздо дольше и используется во многих известных агентах для кодинга? Подписывайтесь, и давайте узнаем!
00:00:35Итак, Ink — это основная библиотека для создания терминальных интерфейсов на React. Я уже делал
00:00:40видео о ней, его можно посмотреть здесь. Но у неё есть свои проблемы. Во-первых,
00:00:44даже простое приложение потребляет более 50 МБ оперативной памяти и имеет жесткое ограничение в 30 кадров в секунду, что
00:00:51нормально для большинства приложений. Но если вы создаете программу, которая транслирует много текста,
00:00:56как, например, агент для кодинга, то этот лимит кадров делает всё очень медленным. Поэтому команда
00:01:00в Anomaly, которая изначально использовала Golang с Bubble Tea для создания OpenCode, захотела переписать
00:01:06его на TypeScript без использования Ink. Так они создали OpenTui. Точнее, они приобрели OpenTui. Они не
00:01:13строили её с нуля, так как Commander FX уже разрабатывал терминальную библиотеку
00:01:18на языке Zig. Anomaly стала его спонсором и построила OpenTui поверх его наработок. Ядро на Zig берет на себя
00:01:24весь тяжелый рендеринг, а привязки TypeScript позволяют писать UI-компоненты на React или Solid. Но самое
00:01:30умное здесь — это интерфейс внешних функций (FFI) среды BUN, который позволяет напрямую
00:01:36обращаться из TypeScript к нативному коду Zig без особых задержек, что и делает OpenTui такой
00:01:42производительной. Она использует Yoga для Flexbox-верстки, поставляется со встроенными компонентами, такими как поля ввода и списки,
00:01:47и даже есть пакет 3.js, который позволяет рендерить 3D-графику WebGPU прямо в терминале,
00:01:54что просто безумие. Давайте увидим OpenTui в действии на простом демо. Есть
00:01:59много способов настроить базовый проект OpenTui. Лично мне нравится использовать "bun create tui",
00:02:04потому что там есть очень полезный мастер установки, который позволяет дать имя проекту и выбрать
00:02:09шаблон. Я выберу React, но позже в видео я объясню различия между этими тремя шаблонами.
00:02:13Итак, после этого у вас появляются стандартные файлы, включая index, который запускает базовый полноэкранный проект.
00:02:17И если мы посмотрим на код, мы увидим здесь, в строке 15, что используется "createCLI" для работы с движком
00:02:21рендеринга OpenTui. А под ним находится "createRoot", который отрисовывает компонент приложения. Если вы
00:02:27знакомы с React, это тот самый код, который обычно монтирует приложение в HTML-файл. Но поскольку мы рендерим в терминал,
00:02:32в этом проекте нет index.html; вместо этого используется кастомный React-реконсилер, который применяет
00:02:37терминальные блоки и текст вместо HTML-компонентов. Над этим у нас есть JSX, использующий компонент "box"
00:02:42и некоторые пропсы Flexbox от Yoga для выравнивания содержимого внутри блока, где отображается ASCII-шрифт и простой текст.
00:02:49Теперь, если вы не хотите, чтобы приложение было полноэкранным, OpenTui поддерживает несколько режимов экрана.
00:02:55Мы можем сменить его на "split footer" с заданной высотой подвала, который фиксирует область рендеринга
00:03:00в нижней части терминала. Но давайте попробуем сделать что-то более интересное, чем просто смена
00:03:05режима экрана. Вот простой TUI с заголовком и полем ввода имени. А теперь посмотрите. С OpenTui вы получаете
00:03:10адаптивность бесплатно. Так что вне зависимости от ширины моего терминала, всё выглядит отлично. И если
00:03:17мы заглянем в код, то увидим очень знакомый синтаксис React. Например, вот здесь у нас "useState",
00:03:21который задает имя. А в поле ввода мы обновляем имя через проп "onInput". И это
00:03:26изменение отображается в тексте. Еще одна крутая особенность OpenTui — это "живая" перезагрузка без HMR.
00:03:32Видите, если я меняю текст на "Goodbye" и сохраняю файл, всё автоматически обновляется.
00:03:37Приятно иметь адаптивный ввод, но иногда текст просто не отображается. Это можно исправить,
00:03:43добавив ширину, что значительно облегчает задачу. А с компонентом "box" у нас есть
00:03:48крутые пропсы, такие как рамка и цвет фона, которые мгновенно освежают терминальное приложение.
00:03:52Опять же, мы можем использовать ASCII-шрифт вместо обычного текста, чтобы заголовок выделялся лучше.
00:03:56Конечно, есть много ASCII-шрифтов на выбор. Помните, поскольку это
00:04:01терминальное приложение, а не веб-страница, оно не рендерит все шрифты вашей системы, а только те, что поддерживает терминал.
00:04:05Мы также можем менять представление при отправке данных, так же, как в обычном приложении React,
00:04:10изменяя состояние по событию submit и отображая другой JSX в зависимости от этого условия. Но вот
00:04:15одна вещь, которую вы вряд ли ожидали от терминала. Если я отправлю своё имя, второе состояние плавно
00:04:20появляется. Это делается с помощью хука "useTimeline" из OpenTui, который задает длительность анимации
00:04:25и целевые параметры. В данном случае у компонента непрозрачность (opacity) равна нулю, а отступ (offset) равен восьми,
00:04:30что означает внешний отступ сверху от центра. В конце анимации отступ равен нулю,
00:04:36а непрозрачность — единице, благодаря обновлению состояний offset и opacity.
00:04:40Эти значения обновляются в пропсах блока. Выглядит немного дергано, потому что анимации в терминале
00:04:45должны перемещаться построчно, как по сетке, но очень круто, что OpenTui позволяет делать это
00:04:50так легко. Еще круче то, что мы можем комбинировать всё изученное, используя верстку flexbox
00:04:55для размещения блоков рядом друг с другом. У нас есть поле ввода с одной стороны и другой блок с другой.
00:05:00При вводе текста и отправке мы можем анимировать передачу значения в другой блок,
00:05:05что очень приятная деталь. И с этого момента можно делать очень многое с помощью OpenTui,
00:05:10например, включить клавиатурную навигацию через хук "useKeyboard", показать системные данные через "node:os",
00:05:14подключить поддержку мыши или виртуализированные списки. И так как всё это работает на базе BUN,
00:05:19можно использовать такие вещи, как "bun:sqlite", "bun:postgres" или делать запросы к внешним данным,
00:05:24как на обычном сайте. Самое приятное, что после компиляции мое приложение весит 71
00:05:28МБ, потому что включает рантайм BUN и реконсилер React. Но когда я запускаю его,
00:05:34оно потребляет менее 50 МБ памяти. А поскольку React настолько популярен,
00:05:39LLM знают его как свои пять пальцев. Поэтому создание приложений на OpenTui может быть очень простым,
00:05:43без необходимости постоянно заглядывать в документацию. Вот такой получился простой
00:05:49обзор OpenTui. Но давайте вернемся к началу видео, где я обещал объяснить
00:05:53разницу между React, Solid и Core. Всё довольно просто, если вы знаете фронтенд-разработку.
00:05:58По сути, все они рендерятся через одно и то же ядро на Zig. Отрисовка в терминале
00:06:02почти идентична. Разница только в том, как вы пишете компоненты
00:06:07и как применяются обновления. React перевыполняет компоненты и сравнивает виртуальное дерево при каждом
00:06:11изменении, что очень похоже на работу виртуального DOM. Solid использует мелкозернистые обновления,
00:06:17поэтому обновляет только то, что изменилось. А Core пропускает всё это, позволяя просто мутировать
00:06:22объекты напрямую. На бумаге React — самый тяжелый, а Core — самый легкий. Но на практике
00:06:27для большинства терминальных приложений разница ничтожна, так как всю тяжелую работу берет на себя ядро на Zig,
00:06:33а значит, выбор фреймворка — это дело личных предпочтений. И хотя приложение на OpenTui
00:06:38поставляется с целым рантаймом BUN и специфическим для фреймворка реконсилером, его
00:06:44производительность и размер всё равно намного меньше, чем у Ink, хотя, конечно, не дотягивают
00:06:50до таких нативных решений, как Ratatouille или Bubble Tea. Но, на мой взгляд, JSX — это лучший
00:06:56и самый интуитивно понятный способ создания UI. И я лучше пожертвую немного размером и памятью,
00:07:02получив гораздо лучший опыт разработки TUI, чем буду использовать легкий, но сложный в написании инструмент.
00:07:09Поэтому, держа это в уме, я бы выбирал OpenTui
00:07:15вместо Ink каждый раз, если когда-нибудь соберусь написать терминальное приложение,
00:07:20что, обещаю, сделаю в ближайшее время.

Key Takeaway

OpenTui предлагает высокопроизводительную альтернативу существующим инструментам разработки терминальных интерфейсов, сочетая интуитивность JSX с эффективностью нативного кода Zig и рантайма Bun.

Highlights

  • OpenTui использует ядро на языке Zig для высокопроизводительного рендеринга терминальных интерфейсов через привязки React, Solid и Core.

  • Интерфейс внешних функций (FFI) среды Bun обеспечивает прямой доступ из TypeScript к нативному коду Zig, минимизируя задержки.

  • OpenTui потребляет менее 50 МБ оперативной памяти при работе, что значительно эффективнее популярных аналогов на React, таких как Ink.

  • Библиотека поддерживает верстку Flexbox на основе Yoga, адаптивные интерфейсы и даже рендеринг 3D-графики через WebGPU и 3.js.

  • Хук useTimeline в OpenTui позволяет реализовывать анимации прямо в терминальной среде, несмотря на сеточную структуру отображения.

Timeline

Проблемы существующих инструментов и появление OpenTui

  • Библиотека Ink для React ограничена 30 кадрами в секунду и потребляет более 50 МБ оперативной памяти.
  • OpenTui разработана командой Anomaly на базе наработок по терминальной библиотеке на языке Zig.
  • Интеграция через Bun FFI позволяет напрямую вызывать Zig из TypeScript без существенных задержек.

Разработчики столкнулись с ограничениями производительности при создании сложных интерфейсов, таких как кодинг-агенты, на базе существующих решений. Переход на связку Zig и Bun обеспечивает высокую скорость рендеринга и низкое потребление ресурсов. Ядро на Zig берет на себя основные вычислительные задачи, оставляя UI-логику за библиотеками вроде React или Solid.

Практическая разработка и возможности рендеринга

  • Настройка проекта выполняется через команду bun create tui с выбором шаблона.
  • Библиотека поддерживает различные режимы отображения, включая полноэкранный и разделенные области.
  • JSX-синтаксис в сочетании с компонентами Box и пропсами Flexbox позволяет создавать адаптивные интерфейсы.
  • Хук useTimeline обеспечивает плавную анимацию элементов в терминале путем изменения состояния непрозрачности и отступов.

Процесс разработки в OpenTui напоминает создание веб-приложений на React: используется привычный синтаксис, стейт-менеджмент и компоненты. Отсутствие DOM компенсируется кастомным реконсилером, который переводит JSX-структуры в терминальные блоки. Поддержка Flexbox упрощает верстку, а возможность работы с SQLite или Postgres через рантайм Bun делает библиотеку полноценным инструментом для создания CLI-приложений.

Сравнение фреймворков и архитектурные выводы

  • Приложение на базе OpenTui весит около 71 МБ из-за включения рантайма Bun и реконсилера.
  • React, Solid и Core используют одно и то же ядро на Zig, различаясь лишь подходом к обновлению компонентов.
  • Для большинства задач производительность всех трех фреймворков в составе OpenTui практически идентична.

Хотя нативные решения вроде Ratatouille или Bubble Tea могут быть более легковесными, OpenTui выигрывает за счет простоты разработки на JSX. Выбор между React, Solid и Core зависит от личных предпочтений, так как основная тяжелая нагрузка делегируется ядру. Высокий уровень производительности и интуитивность разработки делают OpenTui оптимальным выбором для современных терминальных приложений.

Community Posts

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

Write about this video