wterm: Das Ghostty-basierte Web-Terminal von Vercel

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

Transcript

00:00:00Dies ist Wterm, ein webbasierter Terminal-Emulator von Vasell,
00:00:03der direkt im DOM rendert statt auf einem Canvas.
00:00:06Textauswahl, Browsersuche
00:00:08und Screenreader funktionieren damit einfach.
00:00:10Es ist in Zig geschrieben, kompiliert zu einer 12-Kilobyte-WASM-Binärdatei
00:00:14und es gibt ein optionales Backend, das auf LibGhosty basiert,
00:00:17derselben Engine, die das Ghosty-Terminal antreibt,
00:00:19was Ihnen volle Terminal-Kompatibilität im Browser bietet.
00:00:22Aber reicht eine 12-Kilobyte-WASM-Binärdatei
00:00:24wirklich aus, um einen nativen Terminal-Emulator zu ersetzen?
00:00:28Wahrscheinlich nicht, aber abonniert den Kanal und wir finden es heraus.
00:00:33Web-Terminals sind heutzutage fast überall.
00:00:36In Cloud-IDEs wie GitHub Codespaces,
00:00:39Infrastruktur-Tools wie Portainer oder Qualify,
00:00:41und sogar in Desktop-IDEs wie VS Code oder Cursor.
00:00:44Aber sie alle nutzen dafür Xterm.js,
00:00:47weil es schon lange existiert
00:00:49und im Grunde der Standard ist.
00:00:51Xterm hat jedoch ein großes Problem.
00:00:52Es rendert auf ein Canvas-Element.
00:00:54Dinge wie Textauswahl
00:00:56oder das Finden von Wörtern auf einer Seite
00:00:58müssen alle von Grund auf neu implementiert werden,
00:01:00was nicht immer gut funktioniert.
00:01:02Wterm wählt einen komplett anderen Ansatz,
00:01:04indem es direkt im DOM rendert,
00:01:05was bedeutet, dass die Terminalausgabe einfach HTML ist,
00:01:08und der Browser das im Grunde kostenlos erledigt.
00:01:10Aber Wterm kann auch einige wirklich coole Dinge
00:01:13mit diesem HTML-Rendering,
00:01:14wie zum Beispiel nur die Zeile neu zu rendern, die aktualisiert wurde,
00:01:17anstatt das gesamte Terminal bei jedem Frame neu zu rendern.
00:01:20Es kann auch in verschiedenen Frameworks geschrieben werden,
00:01:22wie React oder Vue.
00:01:23Sie können das Theme ändern.
00:01:24Und es gibt auch ein separates Wterm-Ghosty-Paket,
00:01:27das den Zig-Call durch libghosty ersetzt
00:01:29und überraschenderweise besser funktioniert
00:01:31als das andere Web-Ghosty-Projekt,
00:01:33über das wir später im Video noch mehr sprechen werden.
00:01:35Aber für den Moment: Lassen Sie uns Wterm
00:01:37mit einem einfachen Demoprojekt ausprobieren.
00:01:38Nachdem ich Wterm mit React installiert habe,
00:01:40habe ich die Komponente sowie das CSS importiert,
00:01:43und ich rendere die Komponente hier.
00:01:45Wenn ich jetzt die App starte und dann den Browser aufrufe,
00:01:48sehe ich, dass es ein Terminal gibt.
00:01:49Aber wenn ich einen Befehl wie “ls” eingebe,
00:01:51passiert nichts.
00:01:52Und das liegt daran, dass es nicht mit
00:01:53einem anderen Computer verbunden ist, um Informationen zu lesen.
00:01:56Lassen Sie mich das erklären.
00:01:57Im Moment ist der Client nicht mit einem Backend verbunden,
00:01:59also gibt es keinen Ort, von dem es Informationen abrufen kann.
00:02:01Aber wir müssen es mit einer anderen Maschine verbinden.
00:02:04Das könnte mein lokaler Rechner sein
00:02:06oder eine Maschine in der Cloud,
00:02:07und dann ein gefälschtes Terminal oder ein Pseudo-Terminal
00:02:10innerhalb dieser Maschine mit denselben Abmessungen rendern
00:02:13wie die des Clients.
00:02:14Wenn wir also einige Tastatureingaben machen,
00:02:16werden diese Informationen an die andere Maschine gesendet,
00:02:18die diese Befehle ausführt,
00:02:20die Ergebnisse rendert,
00:02:22und all diese Informationen
00:02:23zurück an den Client sendet.
00:02:25Und dieser Datenaustausch muss
00:02:26sehr schnell und mit minimaler Verzögerung erfolgen.
00:02:28Der beste Weg, den Client
00:02:30und die andere Maschine zu verbinden,
00:02:31ist die Verwendung von WebSockets.
00:02:32Lassen Sie uns das also tun.
00:02:34Wir können einen HETS im Server verwenden
00:02:35mit Ubuntu, das ich bereits eingerichtet habe
00:02:37und auf dem Node installiert ist.
00:02:38Und ich habe auch schon einen Wterm-Server
00:02:40mit einem Server-Skript.
00:02:42Wenn wir uns das ansehen,
00:02:43sehen wir, dass wir einen WebSocket-Server
00:02:45auf dem Pfad “/api/terminal” erstellen.
00:02:48Das wird später noch klarer.
00:02:49Und hier unten
00:02:49spawnen wir ein Pseudo-Terminal
00:02:51mit einem Namen, der zu unserem Terminaltyp passt.
00:02:53Hier erfahren Sie, wie Sie Ihren finden, falls Sie neugierig sind.
00:02:55Und hier unten
00:02:56erhalten wir jede Tastatureingabe vom Client,
00:02:58verarbeiten sie auf dem Server,
00:02:59also innerhalb unseres gefälschten Terminals,
00:03:01und senden diese Informationen
00:03:02zurück an den Client.
00:03:03Der Server gibt also alles zurück
00:03:05und nicht nur die Zeile, die gerade aktualisiert wurde.
00:03:07Nun, auf dem Client in der “app.tsx”-Datei
00:03:10stellen wir eine WebSocket-Verbindung
00:03:11zu unserem Server auf dem “/api/terminal”-Port her.
00:03:14Dann verwenden wir den WebSocket-Transform
00:03:16von Wterm, um uns mit dieser URL zu verbinden,
00:03:19mit automatischen Wiederverbindungen.
00:03:21Das ist es, was Tastaturinformationen
00:03:23von hier an den Server sendet.
00:03:24Wir behandeln die Browser-Größenänderung hier,
00:03:26und dann weiter unten
00:03:27verarbeitet die “handleData”-Funktion
00:03:28alle Informationen,
00:03:30die vom Server kommen.
00:03:31Das Coole an dem ZIG-Kern ist,
00:03:33dass er diese Informationen verarbeitet,
00:03:35herausfindet, was geändert wurde,
00:03:36und nur diesen Teil des HTMLs neu rendert.
00:03:39Hier unten müssen die Spalten- und Zeilengröße
00:03:41mit denen auf dem Server übereinstimmen,
00:03:42und alles andere ist ziemlich selbsterklärend.
00:03:45Wenn also Client und Server laufen,
00:03:47kann ich im Browser “ls” drücken
00:03:49und sehen, welche Dateien verfügbar sind.
00:03:52Ich könnte “ls -l” eingeben,
00:03:53um weitere Informationen zu den Dateien zu sehen.
00:03:55Ich kann in ein Verzeichnis wechseln (cd),
00:03:57die Informationen darin ansehen,
00:03:59und auch Dinge tun wie die Liste
00:04:01der laufenden Container anzeigen.
00:04:02Ich kann sogar eine Datei mit Vim öffnen
00:04:03und darin navigieren.
00:04:04Aber auch wenn das alles funktioniert,
00:04:06tut es das nicht perfekt.
00:04:07Ich meine, wenn wir versuchen, Text zu markieren,
00:04:09können wir sehen, dass einige Zeichen
00:04:10völlig unleserlich sind.
00:04:12Um das zu beheben,
00:04:13können wir Wterm mit Ghosty einrichten,
00:04:15indem wir den Ghosty-Core laden
00:04:16und ihn als Prop in React hinzufügen.
00:04:18Sie können jetzt sehen, wenn wir die Serverdatei öffnen
00:04:20und Text markieren,
00:04:22dass alles viel lesbarer ist.
00:04:23Es kann sogar Dinge tun wie
00:04:24OpenCode korrekt rendern,
00:04:26erlaubt uns, Modelle zu wechseln,
00:04:27und Eingabeaufforderungen mit Emoji-Unterstützung zu geben.
00:04:29Wir können sogar sehen, dass Ghosty Farben
00:04:31etwas besser rendert
00:04:31als mit dem Standard-Wterm-Core-Renderer.
00:04:34Aber der Zig-Core ist nur 12 Kilobyte groß,
00:04:36verglichen mit den 400 Kilobyte von Ghosty.
00:04:39Wenn Ihnen die Größe wichtig ist,
00:04:40dann bleiben Sie vielleicht beim Zig-Core.
00:04:43Wie auch immer, das war ein kurzer Überblick über Wterm von Vercel.
00:04:46Natürlich gibt es noch so viele weitere Funktionen,
00:04:48auf die ich nicht eingegangen bin,
00:04:49wie das Konvertieren von Markdown
00:04:51in eine schöne Terminalausgabe,
00:04:52die Nutzung von Bash, um durch gefälschte Dateien zu navigieren,
00:04:55wenn Sie keinen Zugriff auf ein Backend haben.
00:04:57Und es gibt sogar Beispiele
00:04:58dafür, wie man einen SSH-Client
00:05:00über ein Terminal im Browser einrichtet.
00:05:02Aber ich fand Wterm nicht perfekt.
00:05:05Es gab einige Rendering-Probleme,
00:05:06wenn man die Ghosty-Version verwendete,
00:05:08beim Wechseln zwischen NeoVim
00:05:10oder sogar OpenCode.
00:05:11Und um den Ghosty-Renderer zum Laufen zu bringen
00:05:13mit meinem Bun-Frontend,
00:05:15musste ich die WASM-Datei importieren,
00:05:17weil Bun keine Nicht-JS-Dateien
00:05:19aus dem “node_modules”-Ordner kopieren wollte.
00:05:21Aber ich mag den DOM-Rendering-Ansatz,
00:05:23weil man dadurch Barrierefreiheit
00:05:25und native Browser-Funktionen erhält,
00:05:27ohne zusätzliche Arbeit leisten zu müssen,
00:05:29womit Xterm zu kämpfen hatte,
00:05:31obwohl es schon seit mehr als 10 Jahren existiert.
00:05:33Aber Xterm.js hat ein riesiges Ökosystem
00:05:35und ist die bewährte Lösung,
00:05:38also macht man nichts falsch, wenn man sich dafür entscheidet.
00:05:40Es gibt auch GhostyWeb von Coda,
00:05:42das einen anderen Ansatz verfolgt.
00:05:43Es verwendet dieselbe libghosty-Engine,
00:05:45die vom eigentlichen Ghosty-Terminal genutzt wird,
00:05:48aber es ist ein Drop-in-Ersatz für Xterm,
00:05:50verwendet also immer noch den Canvas-Rendering-Ansatz
00:05:52und nutzt dieselbe API,
00:05:54aber Sie erhalten ein besseres Terminal.

Key Takeaway

Wterm bietet als DOM-basierter Terminal-Emulator eine native Browser-Integration und effizientes zeilenweises Rendering, das Xterm.js bei Barrierefreiheit und Suchfunktionen überlegen ist.

Highlights

  • Wterm rendert Terminalinhalte direkt im DOM statt auf ein Canvas-Element, was native Browser-Funktionen wie Textauswahl und Screenreader unterstützt.

  • Der in Zig geschriebene Kern von Wterm umfasst lediglich 12 Kilobyte an WASM-Binärdaten.

  • Wterm erzielt Performance-Optimierungen, indem bei Frame-Aktualisierungen nur die geänderten Zeilen neu gerendert werden, anstatt das gesamte Terminal zu aktualisieren.

  • Die Integration von LibGhosty als optionales Backend ermöglicht eine verbesserte Terminal-Kompatibilität und präzisere Darstellung von Farben und Inhalten, vergrößert das Paket jedoch auf 400 Kilobyte.

  • Die Kommunikation zwischen Client und Server erfolgt über WebSockets, wobei die Terminal-Abmessungen auf beiden Seiten synchronisiert werden müssen.

Timeline

Grundlagen und Architektur von Wterm

  • Wterm nutzt direktes DOM-Rendering für bessere native Browser-Unterstützung.
  • Der Kern basiert auf einer 12 Kilobyte großen Zig-WASM-Binärdatei.
  • Im Vergleich zu Xterm.js entfällt die komplexe Neuentwicklung von Funktionen für Textauswahl und Suche.

Herkömmliche Web-Terminals wie Xterm.js rendern auf Canvas-Elemente, wodurch grundlegende Browser-Funktionen oft manuell nachgebaut werden müssen. Wterm löst dies durch das Rendern als Standard-HTML. Zusätzlich reduziert die effiziente Update-Logik die CPU-Last, da nur veränderte Zeilen statt ganzer Frames aktualisiert werden.

Implementierung und WebSocket-Kommunikation

  • Der Terminal-Client benötigt ein Backend für die Ausführung von Befehlen.
  • WebSockets ermöglichen den schnellen Datenaustausch mit minimaler Verzögerung zwischen Client und Server.
  • Pseudo-Terminals auf dem Server verarbeiten Tastatureingaben und geben Ergebnisse an das DOM zurück.

Die Einbindung von Wterm in Projekte wie React erfordert eine WebSocket-Verbindung, um mit einer entfernten Maschine zu kommunizieren. Ein Server-Skript spawnt ein Pseudo-Terminal, das die Terminal-Größe des Clients spiegelt. Der ZIG-Kern verarbeitet die eintreffenden Server-Daten und aktualisiert gezielt nur die betroffenen HTML-Elemente.

Ghosty-Integration und Limitierungen

  • Die LibGhosty-Engine verbessert die Darstellung von Farben und Inhalten signifikant.
  • Die Paketgröße steigt durch die Ghosty-Integration von 12 KB auf 400 KB an.
  • Trotz technischer Vorteile treten beim Rendern von komplexen Anwendungen wie NeoVim gelegentlich Fehler auf.

Während der reine Zig-Kern extrem leichtgewichtig ist, bietet die optionale Integration von LibGhosty eine höhere Kompatibilität. Dies verbessert die Lesbarkeit von Textmarkierungen und die Unterstützung komplexer Terminal-Anwendungen. Trotz der Vorteile bleibt Xterm.js durch sein weitreichendes Ökosystem weiterhin der Industriestandard für Web-Terminals.

Community Posts

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

Write about this video