- 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
¿Es algo como el viejo GWT?
Mmm... me da curiosidad si de verdad permitirá un desarrollo más seguro en tipos que TS.
Por más que lo vea, parece que están resolviendo un problema fácil de una forma difícil...
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.
Aun así, sí me dan ganas de probarlo.
Opiniones en Hacker News
Hay quienes opinan que, como equipo pequeño, necesitaban desplegar rápido
Tenían un equipo fuerte de ingenieros de Go y una UI compleja que era difícil de escalar con TypeScript/React
Había preocupación de que fuera un framework que "renderiza en canvas", pero no es así
Decidieron construir el frontend usando <a href="https://go-app.dev/" rel="nofollow">https://go-app.dev/</a>
Hay opiniones de que Go no es adecuado para este tipo de trabajo
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
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 quien opina que WASM sirve para ciertos nichos específicos, pero no para construir una web app común
Algunos creen que usar el mismo lenguaje para todos los componentes (frontend/backend/app) tiene un gran valor