El camino de Figma hacia TypeScript: compilando y eliminando nuestro lenguaje de programación personalizado
- Figma había escrito una parte central de su arquitectura de renderizado móvil en un lenguaje de programación personalizado llamado Skew.
- Un lenguaje inventado para obtener mejor rendimiento en el motor de renderizado.
- Muestran cómo migraron automáticamente Skew a TypeScript sin interrumpir el desarrollo ni por un solo día.
El inicio y las limitaciones de Skew
- Skew empezó en Figma como un proyecto secundario.
- En ese momento necesitaban construir rápidamente un visor de prototipos compatible tanto con web como con móvil.
- Se convirtió en un lenguaje de programación compilado completo a JavaScript que permitía optimizaciones más avanzadas y tiempos de compilación más rápidos.
- Con el tiempo, al acumularse el código en Skew, empezaron a aparecer limitaciones.
- Era difícil para un desarrollador nuevo adaptarse.
- No se integraba fácilmente con el resto de la base de código.
- Figma tenía poco ecosistema de desarrolladores fuera de la empresa.
- Las dificultades para extenderlo terminaron superando sus ventajas iniciales.
Factores que posibilitaron la migración a TypeScript
- Mayor soporte de WebAssembly en navegadores móviles.
- Reemplazo de componentes centrales del motor de Skew por sus equivalentes en el motor de C++.
- Al moverse a TypeScript, la pérdida de rendimiento se redujo.
- El crecimiento del equipo permitió asignar recursos para enfocarse en la experiencia de los desarrolladores.
Proceso de conversión de la base de código
- Objetivo: convertir todo el código de Skew a TypeScript.
- Eligieron una migración automatizada en lugar de reescribir manualmente.
- Evitaron ralentizar la velocidad de desarrollo y prevenir errores en tiempo de ejecución y degradaciones de rendimiento para los usuarios.
- Proceso de despliegue en 3 etapas
- Escribir en Skew, compilar Skew
- Mantuvieron el proceso de compilación original, desarrollaron el transpilador y subieron el código de TypeScript en GitHub.
- Escribir en Skew, compilar TypeScript
- Empezaron a desplegar tráfico de producción directamente desde la base de código de TypeScript.
- Los desarrolladores seguían escribiendo en Skew, mientras que el transpilador convertía Skew a TS.
- Escribir en TypeScript, compilar TypeScript
- Se necesitó que TypeScript sea la fuente de verdad para el desarrollo.
- Bloquearon el proceso de generación automática y eliminaron el código Skew de la base de código.
Notas sobre el trabajo del transpilador
- El compilador se compone de frontend y backend.
- Frontend: analiza y comprende el código de entrada, y realiza comprobación de tipos y de sintaxis.
- Conversión a IR (representación intermedia), capturando por completo la semántica y la lógica del código original.
- Backend: convierte la IR a varios lenguajes.
- Un transpilador es un tipo especial de compilador que genera código legible para humanos.
Problemas encontrados durante la migración
- Rendimiento de destructuring de arrays
- Si no se usa destructuring de arrays de JavaScript, se obtiene hasta un 25% de mejora de rendimiento.
- Optimización de "devirtualization" de Skew
- En el proceso de despliegue agregaron pasos extra para que la desvirtualización no rompiera el comportamiento de la base de código.
- En TypeScript importa el orden de inicialización
- El transpilador debe generar código que respete ese orden.
Uso de source maps para mejorar la experiencia de desarrollador
- Se enfocaron en facilitar la migración para la productividad de los desarrolladores y en hacer más fluida la experiencia de depuración.
- Conectan el código compilado con el código fuente mediante source maps.
- El navegador solo entiende JavaScript.
- Con los source maps, el navegador puede saber en qué punto del código fuente debe detenerse al depurar el bundle de JavaScript compilado.
- Creación de source maps en el proceso de 3 etapas
- Generar source map de TypeScript a JavaScript.
- Generar source map de Skew a TypeScript para cada archivo fuente de Skew.
- Componer source maps para crear el mapeo de Skew a JavaScript.
Ejemplo de manejo de compilación condicional
- En Skew se permite compilación condicional con una sentencia
if de nivel superior.
- Las condiciones se definen mediante constantes de tiempo de compilación.
- Se pueden definir diferentes objetivos de build para el mismo código base.
- TypeScript no tiene compilación condicional.
- Se trasladó a ejecutarse en la etapa de bundling.
- Utilizaron
defines y eliminación de código muerto de esbuild.
- Esto causó un efecto secundario: un ligero aumento del tamaño del bundle.
Desarrollo de prototipado en la era TypeScript
- Con la migración de Skew a TypeScript, Figma modernizó su base de código central.
- Abrió el camino para integrarse mucho más fácilmente con código interno y externo.
- Permitió que los desarrolladores trabajen de forma más eficiente.
- En ese momento TypeScript no era adecuado, pero hoy sin duda es la elección correcta.
- Ya están avanzando para aprovechar todos los beneficios de haberse movido a TypeScript.
- Integración con el resto de la base de código.
- Una gestión de paquetes mucho más sencilla.
- Uso directo de nuevas capacidades del ecosistema de TypeScript, entre otras cosas.
Opinión de GN⁺
- Figma llevó a cabo el proceso de pasar de Skew, su lenguaje de programación personalizado, a TypeScript de manera muy sistemática y escalonada. Resulta destacable que lograron hacerlo con migración automática sin detener el desarrollo. Lo considero un buen caso de cómo resolver la deuda técnica al crecer la empresa y adaptarse a los cambios del ecosistema.
- En el tránsito desde un lenguaje de rendimiento especializado a uno de propósito general, el surgimiento de tecnologías como WebAssembly jugó un papel clave. Sugiere que, al elegir tecnología, importa no solo la necesidad inmediata sino también la velocidad y dirección de su evolución.
- Me parece valioso que presenten detalles prácticos aplicables en el día a día, como el uso de source maps centrados en la experiencia del desarrollador o el tratamiento de compilación condicional. Resulta llamativo el proceso de mantener compatibilidad con legado y migrar de forma gradual.
- Para una migración de este tipo en una base de código a gran escala, parece fundamental desarrollar un transformador automático de código. El transpilador construido sobre el compilador de Skew pareció haber sido clave. Es un trabajo que exige experiencia en teoría de compiladores e implementación interna.
- La migración de un lenguaje de programación implica más que convertir código: puede generar un impacto positivo en la cultura y el ecosistema de desarrollo en general. Requiere un enfoque cuidadoso, pero vale la pena si una organización de ingeniería tiene la capacidad para hacerlo.
1 comentarios
Comentario de Hacker News