15 puntos por tsboard 2024-12-30 | 12 comentarios | Compartir por WhatsApp

Hace unos 7 meses presenté por primera vez el proyecto TSBOARD.

En ese momento, tanto el frontend como el backend estaban escritos en TypeScript, y para ejecutar el backend se usaba el runtime de Bun.

Sin embargo, por varias razones terminé rehaciendo el backend desde cero, y lo publico en un repositorio de GitHub separado del proyecto TSBOARD original. Este nuevo backend está escrito en Go, y se distribuirá junto con la versión oficial de TSBOARD en formato binario.


¿Por qué rehacer el backend?

  • El runtime de Bun ofrece un rendimiento realmente excelente. Pero, pese a que también se presenta como un toolkit todo en uno, la gestión de paquetes todavía no alcanza el nivel de npm.
  • Por eso, para usar TSBOARD se necesitaban dos runtimes: Node.js y Bun. Era engorroso y también incómodo para los usuarios.
  • Aunque ahora ya está corregido, al principio hubo un problema por el que no funcionaba en CPUs virtuales, y fue algo crítico porque ni siquiera yo, como desarrollador, podía desplegarlo en otros servidores.
  • (Como han señalado otras personas) claro que se puede resolver con orquestación, pero quería ir más allá de las limitaciones inherentes de los runtimes de JS, que al final siguen teniendo la restricción de single thread, y aprovechar varios hilos.
  • Necesitaba más tipos. Solo con TypeScript no podía saciar esa necesidad.

¿Por qué elegí Go?

  • El nuevo backend debía 1) compilarse, 2) encargarse por sí mismo de la gestión de memoria y 3) no requerir la instalación de algo como un runtime aparte.
  • Después de evaluar Rust, Kotlin, Python, PHP y Go, terminé eligiendo Go, que cumplía las tres condiciones y además era nuevo para mí. (Perdón, PHP)
  • Lo que más me gustó fue la simplicidad de Go, y también las similitudes con TypeScript influyeron bastante en la decisión. Sobre todo, creo que en concurrencia y manejo de memoria fue una mejor opción que las demás alternativas.

Go, ¿qué tal fue usarlo?

  • Me di cuenta de que Go también confirma que no existe un lenguaje con puras ventajas. if err != nil { } es totalmente necesario, pero de verdad resulta muy tedioso. A veces extraño try catch finally.
  • Supongo que por un problema de go-mysql-driver, en un entorno de desarrollo real donde existe el cuello de botella del DB I/O, no se comportó tan rápido como esperaba. (Pueden ver la publicación que subí aquí en GeekNews: https://es.news.hada.io/topic?id=18048)
  • La aplicación implícita de interfaces todavía me resulta un poco extraña. ¿Será que de verdad no querían usar palabras clave como implements o extends?
  • Los punteros sí fueron una grata sorpresa. ¡Especialmente porque no hace falta preocuparse por el momento de liberar memoria!
  • Los distintos tipos, las structs simples pero potentes, y los slices me encantan. Lo mejor es que tiene pocas palabras clave, así que se aprende y se pone en práctica muy rápido.
  • ¡Poder usar hilos ligeros casi por arte de magia con la palabra clave go...! ¡Es una maravilla!

¿Qué tal cambiar el backend de un runtime de JS a Go?

  • Con una vez de hacer algo así fue suficiente.
  • Hice varias pruebas mientras benchmarkeaba la parte de DB I/O, y desde la perspectiva de rendimiento en realidad cuesta notar una gran diferencia entre un runtime de JS y un binario de Go. Por ejemplo, en el caso de sharp, una librería de imágenes muy usada en JS, igual utiliza la librería libvips, y no existen aplicaciones web sin DB I/O.
  • Aun así, aunque me costó muchísimo trabajo, creo que fue un buen cambio y planeo seguir usando solo Go para el backend en adelante.
    • El uso de memoria baja de una forma realmente significativa. Claro, con Rust se podría optimizar todavía más, pero para usar GC, este nivel me deja más que satisfecho.
    • La simplicidad del lenguaje es una locura. Hay pocas palabras clave que memorizar y la mayoría de los patrones de uso ya vienen bastante definidos, así que es fácil de aprender. (Claro, usarlo bien ya es otra historia). Me gustó muchísimo que venga con una gran variedad de tipos primitivos.
    • Y lo más satisfactorio de todo: después de compilar, si tienes el binario, simplemente corre. Ya no quiero volver a instalar cosas extra solo para levantar el backend y ejecutar el código otra vez desde ahí.

¿Cómo se usa?

  • Lamentablemente, el entorno Windows no está soportado. Hay que ejecutar el binario en Linux/Mac.
  • La librería libvips debe estar instalada previamente en el servidor que uses. El binario aprovecha las funciones de esa librería para procesar imágenes.
  • Dejé los detalles explicados en el archivo README.md.

Todavía falta mucho por mejorar, y sigo esperando las valiosas opiniones de otros desarrolladores. Hasta me da rabia conmigo mismo recordar lo mucho que me trabé durante el evento GeekNite. Son bienvenidos los reportes de bugs, las propuestas de mejora o incluso opiniones diferentes.

Este diciembre se me está haciendo especialmente pesado, pero aun así espero que el año nuevo traiga un futuro un poco mejor. Gracias por leer este texto largo. Por último, comparto abajo el enlace a las notas de lanzamiento de TSBOARD v1.0.0.

https://tsboard.dev/board/free/47

12 comentarios

 
angkr 2025-02-03

Lo vi en Damoang.
Es un CMS prometedor. Gracias.

 
tsboard 2025-02-04

Yo también me sorprendí porque hay gente en Damoang que todavía me recuerda. Jaja, ¡voy a esforzarme más para estar a la altura de esas expectativas! 😊

 
dongho42 2025-01-03

¡Es útil!

 
tsboard 2025-02-04

¡Aunque fue tarde, gracias por el comentario! 😃

 
jongyeol 2025-01-02

La aplicación implícita de interfaces todavía me resulta un poco rara. ¿Será que no quisieron usar palabras clave como implements o extends?

Tiene pros y contras, pero una ventaja que a veces se siente clara es que, sin modificar el código de bibliotecas estándar o externas, puedes usar una implementación hecha por otra persona y tratar una parte de ella como una interface que definiste tú. Es como FunctionalInterface de Java, o como aplicar duck typing a un lenguaje compilado. En cambio, si fuera un enfoque en el que implements/extends debe declararse obligatoriamente, para vincularlo con una interface creada por mí habría que implementar un Adapter en medio.

Como desventaja, cuando agregas, quitas o cambias métodos en una interface, la ubicación donde se muestran los errores es distinta en comparación con otros lenguajes de tipado estático, y eso resulta un poco incómodo.

 
tsboard 2025-01-02

¡Ah, ya veo! Había una ventaja en la que ni siquiera había pensado. Por suerte, los mensajes de error, ¿eran de gopls? La extensión de Go para VSCode los detectaba muy bien, así que pude encontrar rápido lo que había omitido o implementado mal. Cuando me familiarice un poco más, creo que yo también podré usarlo mejor algún día. Jaja, ¡gracias por explicarlo en los comentarios! ¡Que tengas un muy feliz Año Nuevo!

 
ifmkl 2025-01-02

¡Buen trabajo! Yo también lo subiré a un servidor de pruebas. ¡Muchos éxitos en el Año Nuevo de 2025!

 
tsboard 2025-01-02

¡Gracias! Pruébenlo y, si no funciona bien o tienen alguna duda, por favor avísenme en cualquier momento. ¡Feliz Año Nuevo!

 
channprj 2025-01-01

¡Te apoyo! 👍🏻

 
tsboard 2025-01-02

¡Muchas gracias por su apoyo! ¡Feliz Año Nuevo!

 
zihado 2024-12-31

¡Te apoyo!

 
tsboard 2025-01-02

¡¡Gracias!!! ¡¡Feliz Año Nuevo!!