5 pontos por GN⁺ 2024-05-05 | 1 comentários | Compartilhar no WhatsApp

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
    1. Escrever em Skew, build em Skew
      • Manteram o processo de build original, desenvolveram um transpilador e fizeram commit do código TypeScript no GitHub
    2. 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
    3. 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

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
    1. Gerar source map de TypeScript → JavaScript
    2. Gerar source map de Skew → TypeScript para cada arquivo-fonte do Skew
    3. 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

 
GN⁺ 2024-05-05
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.