A jornada da Figma para o TypeScript: compilando para remover nossa linguagem de programação personalizada
(figma.com)A jornada da Figma para o TypeScript: compilando para remover nossa linguagem de programação personalizada
- A Figma tinha as partes centrais da arquitetura de renderização mobile escritas em uma linguagem de programação personalizada chamada Skew
- Uma linguagem inventada para obter desempenho adicional no mecanismo de reprodução
- Eles descrevem como migraram automaticamente de Skew para TypeScript sem parar o desenvolvimento por um único dia
O começo e os limites da linguagem Skew
- O Skew começou como um projeto secundário inicial da Figma
- Na época havia a necessidade de construir rapidamente um visualizador de protótipos suportado tanto por web quanto por mobile
- Tornou-se uma linguagem de programação JavaScript compilável de programa inteiro, permitindo otimizações mais avançadas e tempos de compilação mais rápidos
- Com o tempo, conforme o código em Skew se acumulava, as limitações ficaram evidentes
- Dificuldade de adaptação para novos contratados
- Dificuldade de integrar facilmente com o restante da base de código
- Pouco ecossistema de desenvolvedores fora da Figma
- A dificuldade de expansão passou a superar as vantagens originais
Fatores que viabilizaram a migração para TypeScript
- Expansão do suporte a WebAssembly em navegadores mobile
- Substituição dos componentes centrais do mecanismo Skew por seus equivalentes no mecanismo C++
- Foi reduzida a perda de desempenho ao migrar para TypeScript
- O crescimento da equipe permitiu alocar recursos para focar na experiência do desenvolvedor
Processo de conversão da base de código
- Objetivo: converter todo o código Skew para TypeScript
- Escolheram migração automatizada em vez de reescrever manualmente
- Evitar a desaceleração do ritmo de desenvolvimento e prevenir erros de runtime e queda de desempenho para os usuários
- Processo de rollout em 3 etapas
- Escrever em Skew, build em Skew
- Manteram o processo de build original, desenvolveram um transpilador e fizeram commit do código TypeScript no GitHub
- Escrever em Skew, build em TypeScript
- Começaram a rodar tráfego de produção diretamente da base de código TypeScript
- Os desenvolvedores ainda escreviam em Skew, e o transpilador convertia Skew para TS
- Escrever em TypeScript, build em TypeScript
- Tornou-se necessário tornar o TypeScript a fonte da verdade para o desenvolvimento
- Bloquearam o processo de geração automática e removeram o código Skew da base de código
- Escrever em Skew, build em Skew
Observações sobre o trabalho do transpilador
- Um compilador é formado por frontend e backend
- Frontend: analisar e compreender o código de entrada, executar checagem de tipos e checagem sintática
- Converter para IR (representação intermediária) — captura completamente a semântica e a lógica do código de entrada original
- Backend: converter IR para várias linguagens
- Um transpilador é um tipo especial de compilador que gera código legível por humanos
Problemas encontrados durante a migração
- Questões de desempenho de desestruturação de arrays
- Não usar desestruturação de arrays do JavaScript pode melhorar o desempenho em até 25%
- Otimização "devirtualization" do Skew
- Durante o rollout foram adicionadas etapas extras para garantir que a devirtualization não quebrasse o comportamento da base de código
- Em TypeScript, a ordem de inicialização importa
- O transpilador precisa gerar código que respeite essa ordem
Uso de Source Map para a experiência do desenvolvedor
- Foco em facilitar a migração para melhorar produtividade dos desenvolvedores e manter fluida a experiência de depuração
- Conectar código compilado e código-fonte usando source maps
- O navegador entende apenas JavaScript
- Com source maps, o navegador sabe em quais pontos do bundle JavaScript compilado deve parar para alcançar o breakpoint do código-fonte
- Geração de source maps no processo de 3 etapas
- Gerar source map de TypeScript → JavaScript
- Gerar source map de Skew → TypeScript para cada arquivo-fonte do Skew
- Compor source maps para mapear de Skew para JavaScript
Exemplo de tratamento de compilação condicional
- O Skew permite compilação condicional com "if" em nível superior
- Define condições usando constantes de tempo de compilação
- Permite definir diferentes alvos de build no mesmo codebase
- TypeScript não possui compilação condicional
- Alterou-se para fazer isso na etapa de bundling
- Usaram "defines" e remoção de código morto do esbuild
- Teve como efeito colateral um pequeno aumento no tamanho do bundle
Desenvolvimento de prototipagem na era do TypeScript
- Ao migrar o código Skew para TypeScript, a Figma modernizou sua base de código principal
- Abriu caminho para integração muito mais fácil com código interno e externo
- Permitindo que desenvolvedores trabalhem de maneira mais eficiente
- Na época, TypeScript não era a escolha certa, mas hoje é claramente a escolha certa
- Trabalhos de follow-up estão em andamento para aproveitar todos os benefícios da migração para TypeScript
- Integração com o restante da base de código
- Gestão de pacotes muito mais fácil
- Uso direto de novos recursos do ecossistema TypeScript etc.
Opinião do GN⁺
-
A Figma realizou uma transição de Skew, uma linguagem de programação personalizada, para TypeScript de maneira muito metódica e faseada. É impressionante ver que a migração automatizada ocorreu sem interromper o desenvolvimento por um único dia. Acredito que seja um ótimo exemplo de como resolver dívidas técnicas conforme a empresa cresce e se adaptar às mudanças de ecossistema.
-
A passagem de uma linguagem de programação customizada focada em desempenho para uma linguagem de uso geral destacou a importância de mudanças no ambiente tecnológico, como o surgimento de WebAssembly. Mostra que, na escolha tecnológica, não basta atender a necessidade do momento; é preciso considerar a velocidade e a direção da evolução tecnológica.
-
A apresentação de detalhes práticos sobre source maps, experiência do desenvolvedor e tratamento de compilação condicional foi muito útil para referência prática. O processo de manter compatibilidade com legado enquanto migrava progressivamente foi impressionante.
-
Em uma base de código de larga escala, para esse tipo de trabalho parece essencial ter um conversor de código automatizado. Tudo indica que o desenvolvimento de um transpilador baseado no compilador Skew foi central. Isso parece um trabalho que exige conhecimento de teoria de compiladores e implementação interna.
-
A migração de linguagens de programação tem impacto além de uma simples conversão de código. Ela pode trazer mudanças positivas para a cultura de desenvolvimento e para todo o ecossistema. É uma iniciativa que exige uma abordagem cuidadosa, mas que vale a pena tentar caso a organização tenha capacidade.
1 comentários
Comentário do Hacker News
Andrew Chan, um dos participantes do projeto, disse que a Figma já usava TypeScript em outras áreas há quase 10 anos, e durante a maior parte desse período havia mais TypeScript do que Skew. O Skew era usado apenas em algumas áreas de produto, como o motor móvel, o player de prototipagem e recursos de espelhamento.
Foi surpreendente que a Figma tivesse uma linguagem personalizada para JS, e ainda mais surpreendente que ela fosse mais rápida que o TypeScript. No entanto, depois migraram para um TS mais lento.
Segundo Evan Wallace, ex-CTO da Figma, o Skew era de 1,5 a 2 vezes mais rápido que o TypeScript graças a otimizações melhores viabilizadas por um sistema de tipos mais rigoroso.
Achei curioso que, na desestruturação de arrays, o JavaScript cria um iterador que percorre o array em vez de indexá-lo diretamente. Fiquei curioso sobre por que o JS não indexa arrays diretamente.
O Skew parece ter sido apenas com callbacks. Foi mencionado que há recursos modernos de JavaScript, como
async/await, além de um sistema de tipos mais flexível.A Figma criou uma DSL de TypeScript personalizada e um compilador para resolver problemas de segurança, como problemas de permissões.
É uma pena que as grandes empresas tenham suas próprias ferramentas internas, linguagens e Kubernetes e não as compartilhem. Se o Skew fosse open source, talvez teria se tornado um TypeScript melhor.
Fiquei curioso sobre a motivação da Figma para usar WebAssembly.
Lição aprendida: não crie uma linguagem personalizada.
As opiniões contrárias ao TypeScript são interessantes. O TypeScript é uma ferramenta com quase nenhum trade-off e melhora praticamente toda linha de código. Parece que é medo de aprender algo novo, falta de tempo para se dedicar ou má compreensão da utilidade. Se você concorda com os opositores do TypeScript, vale a pena pensar mais profundamente sobre o motivo. Caso contrário, você estará abrindo mão de uma grande vantagem.