14 puntos por GN⁺ 2025-02-26 | 6 comentarios | Compartir por WhatsApp
  • Con el lanzamiento de Dagger Cloud v3, la nueva UI fue escrita con WebAssembly (WASM) y Go
  • Go no suele usarse para desarrollo de UI web, pero eligieron este enfoque para lograr "unificación de la base de código y optimización de rendimiento"
  • En este artículo comparten "el contexto de esta decisión, los desafíos durante la implementación y los resultados finales"

Problema previo: ineficiencia por tener dos bases de código

  • Dagger funciona sobre un DAG (Directed Acyclic Graph) y ofrece visualización tanto en la TUI (interfaz de terminal) como en el dashboard web (Dagger Cloud)
  • Antes, la TUI estaba implementada en Go y la UI web en React/TypeScript
  • Sin embargo, era difícil mantener sincronizadas ambas UI, y en particular la UI web tenía problemas de rendimiento al procesar grandes volúmenes de datos en tiempo real
  • Al manejar flujos complejos de eventos de OpenTelemetry (cientos de miles de spans), se hicieron evidentes la degradación de rendimiento y los problemas de velocidad de la UI en React
  • Además, había que implementar la misma funcionalidad dos veces, lo que suponía una gran carga de desarrollo para un equipo pequeño
  • Por eso consideraron un nuevo enfoque con el objetivo de unificar la base de código y optimizar el rendimiento

La solución elegida: Go + WebAssembly

  • Unificación de la base de código con Go
    • Como la TUI ya estaba implementada en Go, hacer también la UI web en Go permitía reutilizar código
    • Había muchos desarrolladores de Go en el equipo, por lo que esto mejoraba la productividad y facilitaba el mantenimiento
  • Uso de WebAssembly (WASM)
    • Adoptaron WebAssembly para poder ejecutar código Go directamente en el navegador
    • Sin embargo, Go + WASM todavía no cuenta con un ecosistema maduro, así que surgieron varios desafíos:
      • Falta de bibliotecas de componentes → hubo que implementar la UI directamente
      • Límite de memoria de WASM en el navegador (2 GB) → se necesitaba optimización para manejar grandes volúmenes de datos
      • Aun así, la optimización de memoria podía beneficiar tanto a la TUI como a la UI web

Estrategia para minimizar el riesgo del proyecto

  • Uso del framework Go-app
    • Eligieron un framework basado en Go para desarrollar una PWA (Progressive Web App)
    • Ofrecía un modelo basado en componentes similar a React, lo que facilitó la transición
  • Creación y validación de un prototipo
    • Reimplementaron la UI existente tanto como fue posible con Go-app para identificar los principales problemas
    • WASM ya estaba documentado como estándar abierto, y las principales dudas podían resolverse con la documentación de Go-app
    • El mayor problema era el límite de uso de memoria, por lo que se necesitó diseño y optimización para resolverlo

Del prototipo a producción

Estrategias de optimización de rendimiento

  • Optimización del renderizado de grandes volúmenes de logs
    • Era necesario mejorar el rendimiento de renderizado al procesar más de 200 mil líneas de logs
    • Para ello optimizaron la biblioteca de renderizado de terminal virtual midterm,
      → mejorando el rendimiento tanto de la TUI como de la UI web
  • Mejora en la velocidad de parsing de JSON
    • En Go WASM, el parsing de JSON es lento → diseñaron un backend inteligente basado en WebSocket
    • Usaron encoding/gob de Go para optimizar la transferencia de datos
  • Optimización del tamaño del archivo WASM
    • Tamaño inicial del archivo WASM: 32 MB
    • Aplicando compresión Brotli → se redujo a 4.6 MB
    • Como era difícil manejar la compresión desde el CDN, la aplicaron directamente en el proceso de build

Otras mejoras

  • Salvo los problemas de memoria que ya esperaban, la mayoría de las preocupaciones resultaron infundadas
  • Escribir componentes de UI no fue difícil, y la integración con otros servicios (Tailwind, Auth0, etc.) tampoco presentó problemas
  • Fue posible usar paquetes de NPM desde WebAssembly, asegurando interoperabilidad con JavaScript
  • Go-app ofrece más flexibilidad que React en la forma de actualizar componentes, lo que da más libertad para optimizar
  • El análisis de rendimiento puede hacerse con las herramientas de profiling de Go (pprof) y con los profilers integrados del navegador
  • Gracias al soporte de PWA, puede ejecutarse como app de escritorio o móvil, sin necesidad de abrir el navegador

Beneficios obtenidos tras la migración

  • Mejor consistencia de la UI
    • Al usar la TUI y la UI web la misma base de código, se ofrece una UX más consistente
  • Mejoras en rendimiento y uso de memoria
    • Al manejar grandes volúmenes de datos, mejoró la velocidad de renderizado y disminuyó el uso de memoria
  • Mayor productividad del equipo
    • Antes era necesario optimizar por separado la UI web y la TUI,
      y ahora una sola optimización puede aplicarse simultáneamente a ambas interfaces
    • Gracias a eso, pueden concentrarse más en desarrollar nuevas funciones

¿Conviene migrar a Go + WASM?

  • En general no lo recomiendan, pero puede ser útil bajo ciertas condiciones:
    • Equipos con muchos desarrolladores de Go
    • UI complejas donde TypeScript/React muestran límites de rendimiento
    • Necesidad de compartir código entre TUI y UI web
    • Entornos donde se necesita maximizar la velocidad de desarrollo
  • Si se cumplen estas condiciones, Go + WASM puede ser una buena alternativa
    Pero, en la mayoría de los casos, las tecnologías web tradicionales (React, TypeScript, etc.) siguen siendo más adecuadas

6 comentarios

 
minho2da 2025-02-27

¿Es algo como el viejo GWT?

 
bbulbum 2025-02-26

Mmm... me da curiosidad si de verdad permitirá un desarrollo más seguro en tipos que TS.

 
colus001 2025-02-26

Por más que lo vea, parece que están resolviendo un problema fácil de una forma difícil...

 
riki3 2025-02-26

Es más efectivo de lo que parece crear frontends basados en Go. Hay una razón por la que están aumentando los casos de uso.

 
halfenif 2025-02-26

Aun así, sí me dan ganas de probarlo.

 
GN⁺ 2025-02-26
Opiniones en Hacker News
  • Hay quienes opinan que, como equipo pequeño, necesitaban desplegar rápido

    • Pero comentan que tardaron casi un mes en hacer un prototipo, tuvieron que escribir por su cuenta los componentes de UI de Go-app, y además cambiaron de forma importante la arquitectura porque Go WASM es lento al parsear JSON
    • A algunos esto les suena a programación orientada al currículum
  • Tenían un equipo fuerte de ingenieros de Go y una UI compleja que era difícil de escalar con TypeScript/React

    • La demo dio la impresión de ser un equipo con poca experiencia en frontend web
    • La página de registro no se ajusta a la pantalla y, al hacer clic dentro del dashboard, aparece un spinner a pantalla completa y la página se vuelve a cargar
    • Mientras cargan los íconos, se muestra el alt-text
    • Hay quien dice que menos mal que React no fue lo que no escaló
  • Había preocupación de que fuera un framework que "renderiza en canvas", pero no es así

    • Es positivo que la interoperabilidad entre WASM y el DOM ya sea lo suficientemente rápida
    • Pero un binario de 32MB es una gran desventaja
  • Decidieron construir el frontend usando <a href="https://go-app.dev/" rel="nofollow">https://go-app.dev/</a>;

    • Go-app es un paquete para construir PWAs usando Golang y WebAssembly
  • Hay opiniones de que Go no es adecuado para este tipo de trabajo

    • Dicen haber obtenido mejores resultados usando Rust
    • Los binarios wasm hechos con Rust pesan en promedio 240kb y se comprimen bien en la transmisión
  • Sería interesante ver, dentro de unos meses, un seguimiento sobre si este cambio de un stack más pesado a uno con mejor rendimiento pero algo peculiar termina dando resultados positivos

    • Contratar desarrolladores frontend para un proyecto así no será más fácil que encontrar desarrolladores de React
  • El creador de go-app encontró esta publicación y dijo que le sorprendió, además de desear éxito al producto

  • Como Go WASM era lento para parsear JSON, eso llevó a cambios en la arquitectura y a crear un "backend inteligente" para cargar datos gradualmente a través de WebSockets

    • Hay preocupación por problemas de seguridad en los datos gob
  • Hay quien opina que WASM sirve para ciertos nichos específicos, pero no para construir una web app común

    • Una app hecha con go-app carga 3.6MB de código WASM
    • Blazor también tiene el mismo problema: incluso una app simple necesita al menos más de 1MB en la carga inicial
  • Algunos creen que usar el mismo lenguaje para todos los componentes (frontend/backend/app) tiene un gran valor

    • En contraste, usan el enfoque de "TypeScript everywhere", con React en el frontend, NodeJS en el backend y Capacitor en la app