14 pontos por GN⁺ 2025-02-26 | 6 comentários | Compartilhar no WhatsApp
  • Ao lançar o Dagger Cloud v3, a nova UI foi escrita em WebAssembly (WASM) e Go
  • Go normalmente não é usado no desenvolvimento de UI web, mas essa abordagem foi escolhida para "unificar a base de código e otimizar o desempenho"
  • Este texto compartilha "o contexto da escolha, os desafios durante a implementação e o resultado final"

Problema anterior: ineficiência causada por duas bases de código

  • A Dagger opera com base em DAGs (Directed Acyclic Graphs) e oferece visualização disso na TUI (interface de terminal) e no dashboard web (Dagger Cloud)
  • Antes, a TUI era implementada em Go e a UI web em React/TypeScript
  • Porém, era difícil manter sincronização entre as duas UIs, e a UI web em especial apresentava problemas de desempenho ao processar grandes volumes de dados em tempo real
  • Ao lidar com fluxos complexos de eventos do OpenTelemetry (centenas de milhares de spans), ficaram evidentes a degradação de desempenho e os problemas de velocidade da UI em React
  • Também era necessário implementar a mesma funcionalidade duas vezes, o que representava uma grande carga de desenvolvimento para uma equipe pequena
  • Por isso, passou-se a considerar uma nova abordagem com o objetivo de unificar a base de código e otimizar o desempenho

Solução escolhida: Go + WebAssembly

  • Unificação da base de código com Go
    • Como a TUI já era implementada em Go, também implementar a UI web em Go permitia reutilização de código
    • Havia muitos desenvolvedores Go na equipe, o que trazia ganhos de produtividade e facilidade de manutenção
  • Uso de WebAssembly (WASM)
    • O WebAssembly foi adotado para permitir executar código Go diretamente no navegador
    • No entanto, Go + WASM ainda não tem um ecossistema maduro, então havia alguns desafios:
      • Falta de bibliotecas de componentes → foi preciso implementar a UI manualmente
      • Limite de memória do WASM no navegador (2GB) → era necessário otimizar ao lidar com grandes volumes de dados
      • Por outro lado, a otimização de memória poderia beneficiar tanto a TUI quanto a UI web

Estratégia para minimizar os riscos do projeto

  • Uso do framework Go-app
    • Foi escolhido um framework baseado em Go para desenvolvimento de PWA (Progressive Web App)
    • Ele oferece um modelo baseado em componentes semelhante ao React, o que facilitou a transição
  • Criação e validação de protótipos
    • A UI existente foi reimplementada em Go-app na maior medida possível para identificar os principais problemas
    • O WASM já é um padrão aberto bem documentado, e as principais dúvidas puderam ser resolvidas na documentação do Go-app
    • O maior problema era o limite de uso de memória, o que exigiu design e otimizações para resolvê-lo

Do protótipo à produção

Estratégias de otimização de desempenho

  • Otimização da renderização de logs em grande escala
    • Era necessário melhorar o desempenho de renderização ao processar mais de 200 mil linhas de log
    • Para isso, foi otimizada a biblioteca de renderização de terminal virtual (midterm),
      → melhorando o desempenho tanto da TUI quanto da UI web
  • Melhoria na velocidade de parsing de JSON
    • O Go WASM tem parsing de JSON lento → foi projetado um backend inteligente baseado em WebSocket
    • O uso de encoding/gob do Go otimizou a transferência de dados
  • Otimização do tamanho do arquivo WASM
    • Tamanho inicial do arquivo WASM: 32MB
    • Aplicação de compressão Brotli → redução para 4,6MB
    • Como era difícil tratar essa compressão via CDN, ela foi aplicada diretamente no processo de build

Outras melhorias

  • Tirando os problemas de memória já previstos, a maior parte das preocupações não se concretizou
  • Escrever componentes de UI não foi difícil, e a integração com outros serviços (Tailwind, Auth0 etc.) também não apresentou problemas
  • Foi possível usar pacotes NPM no WebAssembly, garantindo interoperabilidade com JavaScript
  • O Go-app oferece mais flexibilidade que o React na forma de atualizar componentes, dando maior liberdade para otimização
  • Ferramentas de profiling do Go (pprof) e o profiler embutido do navegador permitiram analisar o desempenho
  • Graças ao suporte a PWA, foi possível executar como app para desktop/mobile, sem precisar abrir o navegador

Benefícios obtidos após a migração

  • Melhoria na consistência da UI
    • Como a TUI e a UI web passaram a usar a mesma base de código, foi possível oferecer uma UX mais consistente
  • Melhoria de desempenho e uso de memória
    • Ao lidar com grandes volumes de dados, houve melhora na velocidade de renderização e redução no uso de memória
  • Aumento da produtividade da equipe
    • Antes, era necessário otimizar separadamente a UI web e a TUI,
      mas agora uma única otimização pode ser aplicada às duas interfaces ao mesmo tempo
    • Com isso, foi possível focar mais no desenvolvimento de novos recursos

Vale a pena migrar para Go + WASM?

  • Em geral, não é recomendado, mas pode ser útil em condições específicas:
    • Equipes com muitos desenvolvedores Go
    • UIs complexas em que TypeScript/React mostram limites de desempenho
    • Necessidade de compartilhar código entre TUI e UI web
    • Ambientes em que é preciso maximizar a velocidade de desenvolvimento
  • Se essas condições forem atendidas, Go + WASM pode ser uma boa alternativa
    Porém, na maioria dos casos, as tecnologias web existentes (React, TypeScript etc.) continuam sendo mais adequadas

6 comentários

 
minho2da 2025-02-27

É tipo o antigo GWT?

 
bbulbum 2025-02-26

Hmm... fico curioso para saber se isso vai resultar em um desenvolvimento mais seguro em termos de tipos do que com TS.

 
colus001 2025-02-26

Por mais que eu olhe, parece que estão resolvendo um problema simples de um jeito complicado...

 
riki3 2025-02-26

É mais eficaz do que parece criar frontends baseados em Go. Dá para entender por que os casos de uso estão aumentando.

 
halfenif 2025-02-26

Mesmo assim, dá vontade de tentar.

 
GN⁺ 2025-02-26
Opiniões no Hacker News
  • Há a opinião de que, sendo uma equipe pequena, precisam fazer deploy rapidamente

    • Mas dizem que levaram quase um mês para criar um protótipo, tiveram que escrever os próprios componentes de UI em Go-app, e a arquitetura foi bastante alterada por causa do problema de o Go WASM ser lento para fazer parsing de JSON
    • Há a opinião de que isso soa como programação voltada para currículo
  • Havia uma equipe forte de engenheiros Go e uma UI complexa que seria difícil de escalar com TypeScript/React

    • Pela demo, ficou a impressão de que a equipe tinha pouca experiência com frontend web
    • A página de cadastro não se ajusta à tela, e ao clicar dentro do dashboard aparece um spinner em tela cheia e a página recarrega
    • O alt-text é exibido enquanto os ícones estão carregando
    • Há a opinião de que foi bom o React não ter escalado
  • Houve preocupação se seria um framework que “renderiza em canvas”, mas não é o caso

    • É positivo que a interoperabilidade entre WASM e DOM tenha ficado rápida o suficiente
    • Porém, um binário de 32MB é uma grande desvantagem
  • Eles decidiram criar o frontend usando <a href="https://go-app.dev/" rel="nofollow">https://go-app.dev/</a>;

    • Go-app é um pacote para construir PWAs usando Golang e WebAssembly
  • Há a opinião de que Go não é adequado para esse tipo de trabalho

    • Dizem que obtiveram resultados melhores usando Rust
    • Binários wasm feitos em Rust têm em média 240kb e comprimem bem durante a transferência
  • Seria interessante um relatório de acompanhamento daqui a alguns meses sobre se a migração de uma stack mais pesada para uma stack mais performática, mas um tanto incomum, trouxe resultados positivos

    • Contratar um desenvolvedor frontend para esse tipo de projeto não será mais fácil do que encontrar um desenvolvedor React
  • O criador do go-app encontrou esta postagem e ficou surpreso, desejando sucesso ao produto

  • Como o Go WASM era lento para fazer parsing de JSON, isso levou a mudanças na arquitetura e à criação de um “backend inteligente” para carregamento progressivo de dados via WebSockets

    • Há preocupações com problemas de segurança dos dados gob
  • Há a opinião de que WASM é adequado para nichos específicos, mas inadequado para criar aplicações web gerais

    • Um app feito com go-app carrega 3.6MB de código WASM
    • O mesmo vale para o Blazor: mesmo um app simples exige pelo menos mais de 1MB no carregamento inicial
  • Considera-se que há grande valor em usar a mesma linguagem para todos os componentes (frontend/backend/app)

    • Em contrapartida, há quem use a abordagem “TypeScript everywhere”, com React no frontend, NodeJS no backend e Capacitor no app