wterm: Vercelが贈るGhosttyベースのWebターミナル

BBetter Stack
Computing/SoftwareInternet Technology

Transcript

00:00:00これはVasell氏が開発したウェブベースのターミナルエミュレーター、Wtermです。
00:00:03Canvasではなく、直接DOMにレンダリングします。
00:00:06そのため、テキストの選択やブラウザの検索機能、
00:00:08スクリーンリーダーなどがそのまま機能します。
00:00:10Zigで書かれており、12KBのWASMバイナリにコンパイルされます。
00:00:14また、LibGhostyを利用したオプションのバックエンドもあり、
00:00:17Ghostyターミナルを駆動するのと同じエンジンで、
00:00:19ブラウザ上で完全なターミナル互換性を実現します。
00:00:22しかし、12KBのWASMバイナリで
00:00:24本当にネイティブのターミナルエミュレーターの代わりになるのでしょうか?
00:00:28おそらく無理でしょう。チャンネル登録して確かめてみましょう。
00:00:33ウェブターミナルは、今やいたるところにあります。
00:00:36GitHub CodespacesのようなクラウドIDEや、
00:00:39PortainerやQualifyといったインフラツール、
00:00:41VS CodeやCursorなどのデスクトップIDEまで。
00:00:44しかし、そのどれもがXterm.jsを使っています。
00:00:47長年使われてきて、
00:00:49基本的には標準だからです。
00:00:51しかし、Xtermには大きな問題があります。
00:00:52Canvas要素にレンダリングする点です。
00:00:54そのため、テキストの選択や
00:00:56ページ内の単語検索といった機能は、
00:00:58すべてゼロから再実装しなければならず、
00:01:00必ずしもうまくいくとは限りません。
00:01:02Wtermは全く異なるアプローチをとっており、
00:01:04DOMに直接レンダリングします。
00:01:05つまり、ターミナルの出力は単なるHTMLであり、
00:01:08ブラウザが標準機能で処理してくれるのです。
00:01:10さらにWtermは、このHTMLレンダリングを使って
00:01:13興味深いことも行います。
00:01:14フレームごとにターミナル全体を再描画するのではなく、
00:01:17更新された行だけを再描画するのです。
00:01:20ReactやVueなど、様々なフレームワークで
00:01:22記述することも可能です。
00:01:23テーマの変更も可能です。
00:01:24また、別パッケージとしてWterm-ghostyがあり、
00:01:27ZigのコアをLibGhostyに入れ替えることで、
00:01:29他のweb-ghostyプロジェクトよりも
00:01:31驚くほど優れた動作をします。
00:01:33それについては、この動画の後半で詳しく話します。
00:01:35まずは、簡単なデモプロジェクトで
00:01:37Wtermを試してみましょう。
00:01:38ReactにWtermをインストールした後、
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擬似ターミナル(pseudo terminal)を
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最適な方法はWebSocketです。
00:02:31では、それを実装しましょう。
00:02:32さっそくやってみます。
00:02:34Node.jsをインストール済みの
00:02:35Ubuntuサーバーを使います。
00:02:37すでにあるWtermサーバーの
00:02:38サーバー用スクリプトを見てみると、
00:02:40WebSocketサーバーを
00:02:42“/api/terminal”というパスで
00:02:43立ち上げているのがわかります。
00:02:45これについては後ほど説明します。
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ではクライアントのapp.tsxファイルで、
00:03:05“/api/terminal”へ
00:03:07WebSocket接続を行います。
00:03:10そしてWtermのWebSocket変換を使い、
00:03:11自動再接続付きでそのURLに接続します。
00:03:14これがキー入力情報をクライアントから
00:03:16サーバーへ送信します。
00:03:19ブラウザのサイズ変更をここで処理し、
00:03:21下のhandleData関数が、
00:03:23サーバーから送られてくる情報を
00:03:24すべて処理します。
00:03:26ZIGコアの素晴らしい点は、
00:03:27この情報を解析して変更箇所を特定し、
00:03:28その部分だけを再レンダリングすることです。
00:03:30列と行のサイズはサーバー側の設定と一致させる必要があり、
00:03:31他は特に説明不要でしょう。
00:03:33それではクライアントとサーバーを実行し、
00:03:35ブラウザで”ls”を押すと、
00:03:36ファイル一覧が表示されます。
00:03:39“ls -l”を実行して、
00:03:41ファイルの詳細を確認することもできます。
00:03:42ファイルへCD移動し、
00:03:45その中身を確認したり、
00:03:47実行中のコンテナ一覧を表示したりもできます。
00:03:49Vimでファイルを開いて編集することも可能です。
00:03:52しかし、動作はするものの、
00:03:53完璧とは言えません。
00:03:55例えばテキストを選択しようとすると、
00:03:57一部の文字が完全に読めなくなります。
00:03:59これを解決するために、
00:04:01Ghosty版のWtermを使用します。
00:04:02Ghostyコアを読み込み、
00:04:03Reactでpropとして渡すのです。
00:04:04すると、サーバーファイルを開いて
00:04:06テキストを選択しても、
00:04:07以前よりはるかに読みやすくなりました。
00:04:09OpenCodeのレンダリングも正しく行われ、
00:04:10モデルの切り替えや、
00:04:12絵文字に対応したプロンプト入力も可能です。
00:04:13また、デフォルトのZigレンダラーよりも
00:04:15Ghostyの方が色味の再現が優れています。
00:04:16ただ、Zigコアがわずか12KBなのに対し、
00:04:18Ghostyは400KBあります。
00:04:20サイズを重視するなら、
00:04:22Zigコアのままの方がいいかもしれません。
00:04:23以上がVercelのWtermの概要です。
00:04:24Markdownを綺麗なターミナル出力に変換したり、
00:04:26バックエンドがない場合に
00:04:27Bashを使って擬似的にファイル操作したり、
00:04:29ブラウザでSSHクライアントを
00:04:31セットアップする例など、
00:04:31他にも多くの機能があります。
00:04:34ただ、Wtermが完璧だとは思いません。
00:04:36Ghostyの400キロバイトに対し、
00:04:39OpenCodeを行き来する際に
00:04:40レンダリングの不具合が見られました。
00:04:43また、Bun環境のフロントエンドでGhostyを使うには、
00:04:46WASMファイルを直接インポートする必要がありました。
00:04:48Bunがnode_modulesから
00:04:49JS以外のファイルをコピーしてくれないからです。
00:04:51しかし、DOMレンダリングのアプローチは気に入っています。
00:04:52余計な実装をしなくても、アクセシビリティや
00:04:55ブラウザ本来の機能が手に入るからです。
00:04:57これはXtermが10年以上
00:04:58苦労してきた点でもあります。
00:05:00それでもXterm.jsには巨大なエコシステムがあり、
00:05:02実績のある決定版です。
00:05:05こちらを選んでも間違いではありません。
00:05:06他にもCoda氏によるGhostyWebがあり、
00:05:08NeoVimの間を行ったり来たりする時や
00:05:10OpenCodeを使っている時でさえ
00:05:11LibGhostyエンジンを使用していますが、
00:05:13Xtermのドロップイン置き換えとして設計されており、
00:05:15CanvasレンダリングとXtermのAPIを維持しつつ、
00:05:17より優れたターミナル性能が得られます。
00:05:19それほどの手間はかからないはずです。
00:05:21どのライブラリも一長一短ですので、
00:05:23プロジェクトの要件に応じて
00:05:25最適なものを選んでみてください。
00:05:27ご視聴ありがとうございました。
00:05:29また次の動画でお会いしましょう。
00:05:31コードやデモの詳細については、
00:05:33概要欄のリンクから確認してください。
00:05:35それでは。
00:05:38チャンネル登録を忘れずに。
00:05:40Codaが開発したGhostyWebもあります。
00:05:42良い開発ライフを。
00:05:43技術の進化は止まりませんね。
00:05:45次はどんなツールが出るのか楽しみです。
00:05:48それでは、また。
00:05:50ありがとうございました。
00:05:52また見てくださいね。
00:05:54それでは!

Key Takeaway

WtermはDOMへの直接レンダリングと柔軟なバックエンド構成(ZigまたはLibGhosty)を選択することで、従来のCanvasベースのXterm.jsが抱えていたアクセシビリティや検索機能の課題を解決するWebターミナルである。

Highlights

  • WtermはCanvas要素ではなくDOMへ直接レンダリングを行うため、テキスト選択やブラウザ検索、スクリーンリーダー機能が標準で利用可能である。

  • Zigで記述されたコアエンジンは12KBという極めて軽量なWASMバイナリにコンパイルされる。

  • Wtermはフレームごとの全体描画を行わず、更新された行のみを部分再描画する仕組みを採用している。

  • LibGhostyをバックエンドとして統合することで、色再現性の向上や絵文字対応、より高精度なテキストレンダリングが可能になる。

  • Ghosty版は12KBのZigコアに対して400KBのバイナリサイズが必要となる。

Timeline

Wtermの概要とDOMレンダリングのアプローチ

  • WtermはHTML要素(DOM)に直接描画することでブラウザ標準機能との親和性を確保している。
  • Xterm.jsのようなCanvasベースのターミナルでは、テキスト選択や単語検索などの機能を個別に再実装する必要がある。
  • 更新された行のみを再描画する仕組みにより、効率的なパフォーマンスを実現している。

従来のWebターミナルはCanvas要素に依存しており、ブラウザが本来持つテキスト操作機能を制限していた。Wtermはターミナルの出力をHTMLとして処理することで、標準のブラウザ機能をそのまま活用できるように設計されている。

Wtermの実装と通信アーキテクチャ

  • クライアント側のWtermはWebSocketを介してサーバー上の擬似ターミナル(pseudo terminal)と通信する。
  • キー入力をサーバーへ送信し、サーバーで実行した処理結果をクライアントが受け取りレンダリングする。
  • Reactなどのモダンなフレームワーク上でコンポーネントとして利用可能である。

ブラウザ上でターミナルを動作させるには、バックエンドとの接続が不可欠である。サーバー側で実行環境を管理し、WebSocketを通じて入出力を同期させることで、遅延を最小限に抑えながらリモートマシンやコンテナ内の操作を可能にしている。

Ghostyによる拡張とライブラリ選定

  • LibGhostyを利用することで、テキストレンダリングの正確性や色味の再現度を高められる。
  • Zigコアの12KBに対し、Ghosty版は400KBのサイズを要するため、用途に応じた選択が求められる。
  • GhostyWebはXterm.jsのAPI互換性を維持しつつ、エンジンをLibGhostyに置換する選択肢としても存在する。

Wtermは軽量なZigコアと機能豊富なGhostyコアの両方を選択できる柔軟性を持つ。現時点では特定のレンダリング不具合や環境によるWASMインポートの制約が見られるものの、DOMレンダリングという手法自体が、長年Canvas実装で苦労してきたWebターミナルのアクセシビリティ課題に対する実用的な解となっている。

Community Posts

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

Write about this video