5 Punkte von GN⁺ 2024-05-05 | 1 Kommentare | Auf WhatsApp teilen

Figma auf dem Weg zu TypeScript: Eine benutzerdefinierte Programmiersprache durch Kompilierung entfernen

  • Figma hat Kernbestandteile der Rendering-Architektur für Mobilgeräte in einer benutzerdefinierten Programmiersprache namens Skew entwickelt.
    • Eine Sprache, die für die Playback-Engine erfunden wurde, um zusätzliche Performance zu gewinnen.
    • Es wird gezeigt, wie Skew vollständig und automatisch nach TypeScript migriert wurde, ohne den Tag der Entwicklung auch nur für einen Tag zu pausieren.

Die Anfänge und Grenzen der Sprache Skew

  • Skew begann bei Figma als Nebenschauplatz-Projekt.
    • Damals musste schnell ein Prototyp-Viewer gebaut werden, der sowohl im Web als auch auf Mobilgeräten funktioniert.
    • Daraus wurde eine vollständig kompilierbare JavaScript-Programmiersprache, die fortgeschrittenere Optimierungen und schnellere Kompilierungszeiten ermöglichte.
  • Mit der Zeit traten durch den wachsenden Skew-Code Grenzen zutage.
    • Es war schwer für neue Mitarbeitende, sich einzuarbeiten.
    • Es ließ sich nicht leicht mit dem restlichen Code-Bestand integrieren.
    • Außerhalb von Figma gab es ein unzureichendes Entwickler-Ökosystem.
    • Die Schwierigkeit der Erweiterung überwog schließlich den ursprünglichen Vorteil.

Faktoren, die die Migration zu TypeScript ermöglichten

  • Steigende WebAssembly-Unterstützung in mobilen Browsern.
  • Austausch zentraler Komponenten der Skew-Engine durch entsprechende Komponenten der C++-Engine.
    • Der Umstieg auf TypeScript verursachte nur geringen Performance-Verlust.
  • Mit dem Teamwachstum konnten Ressourcen für Developer Experience bereitgestellt werden.

Codebase-Umstellungsprozess

  • Ziel: Den gesamten Skew-Code in TypeScript umstellen.
    • Statt manuell neu zu schreiben wurde eine automatisierte Migration gewählt.
    • Vermeidung von Entwicklungseinbußen und von Laufzeitfehlern sowie Performance-Verlusten für Nutzer.
  • 3-stufiger Rollout-Prozess
    1. Skew schreiben, Skew-Build
      • Der ursprüngliche Build-Prozess wurde beibehalten, ein Transpiler entwickelt und TypeScript-Code in GitHub eingecheckt.
    2. Skew schreiben, TypeScript-Build
      • Produktions-Traffic wurde direkt aus der TypeScript-Codebasis ausgerollt.
      • Entwickler schreiben weiterhin Skew, und der Transpiler wandelt Skew nach TS um.
    3. TypeScript schreiben, TypeScript-Build
      • TypeScript-Code musste zur "Single Source of Truth" für die Entwicklung werden.
      • Der automatisierte Generierungsprozess wurde abgeschaltet und Skew-Code aus der Code-Basis entfernt.

Hinweise zur Transpiler-Implementierung

  • Ein Compiler besteht aus Frontend und Backend.
    • Frontend: Parsen und Verstehen des Eingabecodes, Typprüfung, Syntaxprüfung.
    • Konvertierung in IR (Intermediate Representation), wobei Semantik und Logik des ursprünglichen Eingangscodes vollständig erfasst werden.
    • Backend: Umwandlung der IR in verschiedene Sprachen.
  • Ein Transpiler ist eine spezielle Art von Compiler, die lesbaren Code erzeugt.

Probleme während der Migration

  • Performance-Problem bei Array-Destructuring
    • Ohne JavaScript-Array-Destructuring waren bis zu 25 % mehr Performance möglich.
  • Skews „devirtualization“-Optimierung
    • Während des Rollouts wurde ein zusätzlicher Schritt eingeführt, damit devirtualization die Codebasis nicht bricht.
  • In TypeScript ist die Initialisierungsreihenfolge wichtig.
    • Der Transpiler musste Code erzeugen, der diese Reihenfolge respektiert.

Source-Maps für Developer Experience

  • Fokus auf eine einfache Migration und eine reibungslose Debugging-Erfahrung zur Verbesserung der Entwicklerproduktivität.
  • Verbindung von kompiliertem Code und Quellcode über Source Maps.
    • Der Browser versteht nur JavaScript.
    • Durch Source Maps kann der Browser erkennen, wo im kompilierten JavaScript-Bundle der Haltepunkt im Quellcode gesetzt werden soll.
  • Source Maps-Erstellung im 3-stufigen Prozess
    1. Erstellung der TypeScript → JavaScript Source Maps
    2. Für jede Skew-Quelldatei Erstellung der Skew → TypeScript Source Maps
    3. Quelle zusammenfügen, um Mapping von Skew nach JavaScript zu erzeugen

Beispiel für bedingte Kompilierung

  • In Skew wird bedingtes Kompilieren über ein Top-Level-if ermöglicht.
    • Festlegen der Bedingungen durch Compile-Time-Konstanten.
    • Definition unterschiedlicher Build-Ziele für die gleiche Codebasis.
  • TypeScript hat keine bedingte Kompilierung.
    • Die Verarbeitung wurde in den Bundling-Schritt verschoben.
    • Nutzung von esbuild defines und Dead-Code-Elimination.
    • Eine Nebenwirkung war eine leichte Erhöhung der Bundle-Größe.

Prototyping im TypeScript-Zeitalter

  • Durch die Migration von Skew-Code zu TypeScript wurde Figma seine Kern-Codebasis modernisiert.
    • Ein weitaus einfacherer Weg eröffnet sich zur Integration von internem wie externem Code.
    • Entwickler können effizienter arbeiten.
  • Damals war TypeScript ungeeignet, heute ist es eindeutig die richtige Wahl.
  • Weitere Arbeit läuft, um alle Vorteile der TypeScript-Migration zu nutzen:
    • Integration mit dem Rest der Codebasis.
    • Erheblich vereinfachtes Paket-Management.
    • Direkte Nutzung neuer Möglichkeiten im TypeScript-Ökosystem.

GN⁺-Meinung

  • Figma hat den Übergang von der benutzerdefinierten Programmiersprache Skew zu TypeScript sehr systematisch und schrittweise durchgeführt. Besonders beeindruckend war, dass Skew automatisiert zu TypeScript migriert wurde, ohne den Entwicklungsbetrieb zu unterbrechen. Dies ist ein gutes Beispiel dafür, wie ein wachsendes Unternehmen technischen Schulden abbauen und mit Veränderungen im Ökosystem Schritt halten kann.

  • Der Wechsel von einer auf Performance optimierten, eigenen Sprache zu einer universellen Sprache zeigte, wie wichtig technologische Veränderungen wie das Aufkommen von WebAssembly sind. Dass man bei der Technologieauswahl nicht nur den kurzfristigen Bedarf, sondern auch die Geschwindigkeit und Richtung der technologischen Entwicklung berücksichtigt, ist entscheidend.

  • Die praxisnahen Details zum Einsatz von Source Maps für Developer Experience und zur bedingten Kompilierung sind nützlich. Besonders eindrucksvoll ist der schrittweise Migrationsweg bei gleichzeitiger Wahrung der Kompatibilität mit Legacy-Code.

  • Für eine so große Codebasis ist ein automatisierter Code-Konverter offenbar unverzichtbar. Die Entwicklung eines Transpilers auf Basis des Skew-Compilers scheint dabei zentral gewesen zu sein. Diese Arbeit erfordert eindeutig Expertise in Compiler-Theorie und interner Implementierung.

  • Die Migration einer Programmiersprache hat mehr Auswirkungen als eine bloße Codeumwandlung. Sie kann Entwicklungs- und Ökosystemkultur positiv beeinflussen. Sie erfordert eine sorgfältige Herangehensweise, ist aber bei einer reifen Entwicklungsmannschaft ein realistisches Vorhaben.

1 Kommentare

 
GN⁺ 2024-05-05
Hacker News Kommentar
  • Andrew Chan, ein Projektmitwirkender zufolge, hat Figma fast zehn Jahre lang TypeScript in anderen Bereichen eingesetzt, und in der überwiegenden Zeit war TypeScript häufiger im Einsatz als Skew. Skew wurde in einigen Produktbereichen verwendet, darunter Mobile Engine, Prototyping-Player und die Mirroring-Funktion.

  • Figma zu haben, dass es eine benutzerdefinierte Sprache für JavaScript gab, war überraschend – noch erstaunlicher war, dass sie schneller als TypeScript war. Sie migrierten dann später zu langsamerem TypeScript.

  • Evan Wallace (ehemaliger Figma-CTO) sagt, dass Skew dank eines strengeren Typsystems 1,5- bis 2-mal schneller war als TypeScript, weil dadurch bessere Optimierungen möglich wurden.

  • Es ist interessant, dass JavaScript beim Array-Destructuring einen Iterator über das Array aufbaut, statt direkt zu indexieren. Ich frage mich, warum JS nicht direkt im Array indexiert.

  • Skew scheint nur Callbacks zu haben gehabt zu haben. Moderne JavaScript-Features wie async/await sowie ein flexibleres Typensystem wurden genannt.

  • Figma hat eine benutzerdefinierte TypeScript-DSL plus Compiler geschrieben, um Sicherheitsprobleme wie Berechtigungsprobleme zu lösen.

  • Jede große Firma hat ihre eigenen internen Tools, Sprachen und Kubernetes, gibt aber nicht, was sie hat, nicht frei. Schade. Wäre Skew Open Source gewesen, hätte es zu einem besseren TypeScript werden können.

  • Ich bin neugierig, warum Figma auf WebAssembly gesetzt hat.

  • Die Lektion, die man daraus ziehen kann: Baue keine eigene Sprache.

  • Die Argumente derer, die TypeScript ablehnen, sind interessant. TypeScript ist ein Werkzeug mit fast keinen Nachteilen, das fast jede Codezeile verbessert. Es wirkt so, als hätten sie Angst vor Neuem, wollten keine Zeit investieren oder die Nützlichkeit falsch einschätzen. Wenn du den Einwänden der TypeScript-Gegner zustimmst, lohnt es sich, genauer über die Gründe nachzudenken. Sonst musst du erhebliche Nachteile in Kauf nehmen.