5 points par GN⁺ 2024-05-05 | 1 commentaires | Partager sur WhatsApp

Le passage de Figma vers TypeScript : compiler et éliminer un langage de programmation personnalisé

  • Figma écrivait les parties essentielles de son architecture de rendu mobile dans un langage de programmation personnalisé appelé Skew.
    • Un langage inventé pour obtenir des performances supplémentaires dans le moteur de replay.
    • Voici comment ils ont migré automatiquement Skew vers TypeScript sans interrompre le travail un seul jour.

Les débuts et les limites du langage Skew

  • Skew a commencé chez Figma comme un projet annexe.
    • À l’époque, il fallait construire rapidement un visualiseur de prototypes compatible web et mobile.
    • Il est devenu un langage de programmation JavaScript compilé de bout en bout, permettant des optimisations plus avancées et des temps de compilation plus rapides.
  • À mesure que le code Skew s’accumulait, ses limites ont fini par apparaître.
    • Les nouveaux employés avaient du mal à s’adapter.
    • Il n’était pas facilement intégrable avec le reste de la base de code.
    • Il y avait peu d’écosystème développeur en dehors de Figma.
    • Les difficultés d’extension ont fini par dépasser les avantages initiaux.

Les facteurs qui ont rendu la migration vers TypeScript possible

  • Le soutien à WebAssembly s’est accru dans les navigateurs mobiles.
  • Remplacement des composants centraux du moteur Skew par ceux du moteur C++ correspondant.
    • Le passage à TypeScript n’a plus entraîné de perte de performance sensible.
  • La croissance de l’équipe a permis d’allouer des ressources pour se concentrer sur l’expérience développeur.

Processus de transformation de la base de code

  • Objectif : convertir l’ensemble du code Skew en TypeScript.
    • Choix d’une migration automatisée plutôt que d’une réécriture manuelle.
    • Préserver la vitesse de développement et éviter les régressions de bugs d’exécution et de performance côté utilisateurs.
  • Processus de déploiement en trois étapes
    1. Écriture en Skew, build Skew
      • Conserver le pipeline de build d’origine, développer le transpileur, enregistrer le code TS sur GitHub.
    2. Écriture en Skew, build TypeScript
      • Déployer directement le trafic de production à partir de la base de code TypeScript.
      • Les développeurs écrivent toujours en Skew, le transpileur convertit Skew en TS.
    3. Écriture en TypeScript, build TypeScript
      • Faire du code TS la source de vérité pour le développement.
      • Arrêter le processus de génération automatique et supprimer le code Skew de la base de code.

Remarques sur le travail du transpileur

  • Le compilateur se compose d’un front-end et d’un back-end.
    • Front-end : analyse syntaxique et compréhension du code d’entrée, contrôle de types, vérification syntaxique.
    • Conversion en IR (intermediate representation) — capture complète de la sémantique et de la logique du code source d’origine.
    • Back-end : conversion de l’IR vers divers langages.
  • Le transpileur : un type spécial de compilateur qui génère du code lisible par un humain.

Problèmes rencontrés pendant la migration

  • Les problèmes de performance dus au destructuring de tableaux
    • En évitant le destructuring de tableaux JavaScript, on peut gagner jusqu’à 25 % de performance.
  • L’optimisation de la « devirtualization » de Skew
    • Un pas supplémentaire a été ajouté au déploiement afin que la devirtualization ne casse pas le comportement de la base de code.
  • En TypeScript, l’ordre d’initialisation compte.
    • Le transpileur doit générer un code qui respecte cet ordre.

Utilisation des source maps pour l’expérience développeur

  • Pour les développeurs, l’objectif était de faciliter la migration et de fluidifier le débogage.
  • Relier le code compilé et le code source avec les source maps.
    • Le navigateur ne comprend que JavaScript.
    • Les source maps permettent au navigateur de savoir à quels points d’arrêt se placer dans le bundle JavaScript compilé.
  • Génération des source maps dans le processus en trois étapes
    1. Générer une source map TypeScript → JavaScript
    2. Générer une source map Skew → TypeScript pour chaque fichier source Skew.
    3. Composer les source maps pour créer le mapping Skew → JavaScript.

Cas de gestion de la compilation conditionnelle

  • Skew autorise la compilation conditionnelle via une instruction if de haut niveau.
    • Utilisation de constantes de compilation pour définir les conditions.
    • Définition de différentes cibles de build dans la même base de code.
  • TypeScript ne propose pas de compilation conditionnelle.
    • La logique a été déplacée vers l’étape de bundling.
    • Utilisation des fonctionnalités defines et de dead code elimination d’esbuild.
    • Effet secondaire : une légère augmentation de la taille du bundle.

Développement de prototypage à l’ère TypeScript

  • La migration du code Skew vers TypeScript a modernisé le cœur de la base de code de Figma.
    • Elle a ouvert une voie bien plus simple pour intégrer le code interne et externe.
    • Les développeurs peuvent travailler de manière plus efficace.
  • À l’époque, TypeScript n’était pas adapté, mais il est désormais clairement le bon choix.
  • Les travaux de suivi pour profiter pleinement des avantages de la migration vers TypeScript sont en cours.
    • Intégration avec le reste de la base de code.
    • Gestion des packages bien simplifiée.
    • Utilisation directe de nouvelles fonctionnalités de l’écosystème TypeScript, etc.

Opinion de GN⁺

  • Figma a réalisé une transition de Skew, son langage de programmation personnalisé, vers TypeScript de manière très structurée et progressive. Le fait d’avoir mis en place une migration automatisée sans interruption du développement est impressionnant. Je pense que c’est un bon exemple de résolution de la dette technique liée à la croissance de l’entreprise et d’adaptation aux changements de l’écosystème.

  • Dans un passage d’un langage personnalisé focalisé sur la performance vers un langage généraliste, l’émergence de WebAssembly a joué un rôle clé. Cela montre qu’au moment de choisir une technologie, il faut certes répondre aux besoins immédiats, mais aussi tenir compte de la vitesse et de la direction de l’évolution technologique.

  • Les détails concrets autour de la source map au bénéfice de l’expérience développeur, de la compilation conditionnelle, etc. sont utiles en pratique. La migration progressive en conservant la compatibilité avec l’existant est impressionnante.

  • Pour ce type de travail sur une base de code à grande échelle, développer un convertisseur de code automatisé semble indispensable. Le cœur du projet semble avoir été le développement d’un transpileur reposant sur le compilateur Skew. Cela paraît être un travail demandant une vraie expertise en théorie des compilateurs et en implémentation interne.

  • La migration d’un langage de programmation dépasse la simple conversion de code. Elle peut entraîner des changements positifs dans la culture et l’écosystème de développement dans leur ensemble. L’approche doit être prudente, mais cela peut valoir la peine si la capacité d’une organisation le permet.

1 commentaires

 
GN⁺ 2024-05-05
Commentaires Hacker News
  • Selon Andrew Chan, qui a participé au projet, Figma utilisait déjà TypeScript depuis près de 10 ans dans d'autres parties, et pendant la majeure partie de cette période, il y avait plus de TypeScript que de Skew. Skew a été utilisé dans certaines parties du produit, comme le moteur mobile, le player de prototypage et la fonction de mirroring.

  • Il était surprenant que Figma ait eu un langage personnalisé pour le JS, et encore plus surprenant que ce langage ait été plus rapide que TypeScript, avant de migrer plus tard vers un TypeScript plus lent.

  • Selon Evan Wallace, ancien CTO de Figma, Skew était 1,5 à 2 fois plus rapide que TypeScript grâce à de meilleures optimisations rendues possibles par un système de types plus strict.

  • C’est intéressant que, lors de la décomposition d’un tableau, JavaScript construise un itérateur qui parcourt le tableau au lieu d’indexer directement dans le tableau. Je suis curieux de savoir pourquoi JS ne fait pas d’indexation directe dans les tableaux.

  • Skew semble n’avoir été basé que sur des callbacks. Des fonctionnalités JavaScript récentes comme async/await et un système de types plus flexible sont mentionnés.

  • Figma a écrit un DSL TypeScript personnalisé + compilateur afin de résoudre des problèmes de sécurité comme ceux liés aux permissions.

  • Chaque entreprise possède ses propres outils internes, langages et Kubernetes, et ne les partage pas. C’est dommage, car si Skew avait été open source, il aurait peut-être donné un meilleur TypeScript.

  • Je me demande quelle était la motivation de Figma pour utiliser WebAssembly.

  • Leçon à retenir : ne créez pas de langage personnalisé.

  • Les opinions de ceux qui sont contre TypeScript sont intéressantes. TypeScript est un outil qui améliore presque chaque ligne de code avec peu ou pas d’inconvénients. Ils semblent avoir peur d’apprendre quelque chose de nouveau, ne pas vouloir y consacrer de temps, ou mal comprendre son utilité. Si vous êtes d’accord avec les opposants à TypeScript, il faut réfléchir plus en profondeur à leurs raisons; sinon, les conséquences peuvent être importantes.