
669 - Crear una web app en Rust y React en Arch Linux (Sin Morir en el Intento)
Es fácil crear una web app en #rust y typescript utilizando los frameworks #axum y #react para implementar el #backend y el #frontend en #linux y #docker
En los últimos episodios te he hablado de desarrollo de aplicaciones utilizando ArchLinux, como por ejemplo en el episodio 652 que titulé Que distro Linux utilizar para programar, o mas concretamente el episodio 545 que titulé Mamá quiero ser full stack developer. Esto no es solo relativo al desarrollo de aplicaciones y herramientas para Linux, que también, sino mas bien está enfocado en el desarrollo en Linux. En los últimos tiempos ando metido en el desarrollo de un par de aplicaciones web que me tienen mas que emocionados, y que hace que me reafirme en el convencimiento de que me encuentro en el mejor ecosistema que se puede tener para el desarrollo. Así en este episodio te quiero hablar sobre el desarrollo de aplicaciones web en Linux, en concreto en ArchLinux, utilizando Rust en el backend y React en el frontend.

Cómo crear una web app en Rust y React en Arch Linux (Sin Morir en el Intento)
Unas pinceladas sobre este episodio
Con este episodio quiero compartir mi experiencia en el desarrollo de una web app en ArchLinux, utilizando Rust y TypeScript. Y es que si bien inicialmente puedes pensar que es algo realmente complejo, la realidad, es que al final no es nada difícil. Es mas, una vez haces la primera, el resto, no tiene mucha complejidad, salvo casos puntuales o particulares de cada una de las aplicaciones.
Sobre el entorno de desarrollo
No te descubriré nada nuevo si te digo que estoy utilizando Neovim como entorno de desarrollo. La ventaja que me ofrece respecto a otras soluciones es su ligereza y que me permite, con una sola herramienta trabajar tanto con Rust como como TypeScript.
Además de Neovim, estoy utilizando just
, que es una herramienta para la línea de comandos, que me permite implementar mis propios comandos
particularizados a mis necesidades. En concreto, sencillos comandos para levantar el front o el back, para compilar o para crear el docker. De esta forma, me centro en el desarrollo y me dejo de lado esos pequeños inconvenientes que en otras ocasiones no hacen mas que despistarme.
Un ejemplo del justfile
que estoy utilizando sería el siguiente,
user := "atareao"
name := `basename ${PWD}`
version := `git tag -l | tail -n1`
list:
@just --list
dev:
cd front && pnpm i && pnpm run build && rm -rf ../back/static && mkdir ../back/static && cp -r ./dist/* ../back/static
cd back && RUST_LOG=debug cargo run
front:
cd front && pnpm run dev
back:
cd back && RUST_LOG=debug cargo run
build:
cd front && pnpm install --package-lock-only
cd back && cargo generate-lockfile
@docker build --tag={{user}}/{{name}}:{{version}} .
push:
@docker push {{user}}/{{name}}:{{version}}
Así por ejemplo, con tan solo ejecutar just dev
levanta el servicio para que pueda probarlo en vivo y en directo.
Además de esto, estoy utilizando Docker
para empaquetar el desarrollo y poder desplegarlo mas adelante en un VPS.
Sobre el backend
Actualmente todo los backends que estoy desarrollando en mi tiempo libre están implementados con Rust y Axum como framework. Pero, no pienses que este es el primer framework web que he utilizado, ni mucho menos.
Tengo que decirte que soy de mucho probar. Mas que ver un vídeo en el que alguien me cuenta lo maravilloso que es este framework o este otro, prefiero probarlos por mi mismo, y llegar a mis propias conclusiones. Una cosa es lo que te cuentan y otra cosa muy distinta es la realidad, que en muchos casos no se parece en absolutamente nada.
Pero además Axum, como Actix o Rocket son desarrollos muy vivos. Están en continua actualización, con lo que es muy probable, que los artículos que encuentres en internet no se parezcan mucho a la realidad.
Respecto a la base de datos que estoy utilizando actualmente es SQLite. Y estoy utilizando esta base de datos simplemente para facilitarme el desarrollo. Cuando lo pase a producción migraré a PostgreSQL que es mi base de datos de cabecera.
Parta trabajar con la base de datos estoy utilizando sqlx, que si bien no es un ORM, lo cierto es que es realmente sencillo de utilizar.
Sobre el frontend
Tengo que confesarte que le tenía miedo al frontend. Hasta el momento he utilizado vanilla JavaScript junto con jinja2, para los frontales que he ido haciendo para aplicaciones web. Sin embargo, en un desarrollo como estos que estoy haciendo pensaba que se me iría de las manos y por eso estuve dando vueltas a utilizar un framework.
En este caso, al igual que con el backend, le he dado muchas vueltas a los framework que hay en el mercado. He probado tanto Svelte, como Solidjs, y React. Lo cierto es que he ido y he venido de uno a otro. Hice los tutoriales de Svelte, e incluso algún pequeño desarrollo, pero por algún tipo de razón no terminaba de casar conmigo. Luego probé con React, pero me despistó mucho la opción de funcional y por clases. Finalmente por clases, que es lo que a mi me gusta mas.
En este caso para todo lo relacionado con TypeScript estoy utilizando PNpM con lo que actualmente me encuentro muy cómodo.
Como herramienta de compilación estoy utilizando Vite, que tiene algunas características que realmente facilitan el trabajo, como son el inicio instantáneo o el Hot Module Replacement, que te permite desarrollar en directo. Y en particular estoy utilizando el plugin @vite/plugin-react-swc.
Por último queda TypeScript vs JavaScript. Dado que estos proyectos que estoy implementando tienen visos de convertirse en algo complejo, me he decantado por TypeScript. Y es que, TypeScript me da una seguridad, no se si falsa, pero por lo menos me siento más cómodo.
Por último, una de los elementos esenciales para el rápido desarrollo ha sido MUI. Se trata de una librería de componentes para React, que es una auténtica delicia. Al igual que me sucedió con Axum o con React, con MUI también he tenido mis vueltas. He probado otras librerías de componentes de React, porque como de costumbre, a pesar de que puedes encontrar decenas de artículos hablando de librerías, hecho en falta ese artículo realista de alguien que ha probado las librerías y te dice la realidad.
La integración
El objetivo no es levantar un frontend y un backend por separado, con dos servidores independientes. Mi objetivo desde el principio es tener un único servidor funcionando. El backend que sea el que se encargue de servir todo. Y así es como lo hecho de la mano de Axum.
Por supuesto que esto tiene el inconveniente que cuando hay que hacer cualquier cambio en cualquiera de los dos lados, es necesario sacar una nueva versión, y desplegarla, pero, la verdad, es que prefiero hacerlo de esta manera.
En el lado del backend, toda la magia recae en estas pocas líneas de código,
let app = Router::new()
.nest("/api/v1", api_routes)
.fallback_service(ServeDir::new("static")
.fallback(ServeFile::new("static/index.html")))
.layer(TraceLayer::new_for_http())
.layer(cors);
Mientras que en la parte del frontend esa magia la puedes encontrar aquí,
render = () => {
return (
<AuthContextProvider>
<BrowserRouter>
<Routes>
<Route path="/" element={<MainLayout />} >
<Route path="about" element={<AboutPage />} />
</Route>
<Route path="/" element={<ProtectedLayout />} >
<Route index element={<HomePage />} />
</Route>
<Route path="/" element={<AuthLayout />} >
<Route path="login" element={<LoginPage />} />
<Route path="register" element={<RegisterPage />} />
</Route>
</Routes>
</BrowserRouter>
</AuthContextProvider>
);
}
Los despliegues
Esto ya lo podías imaginar, pero, por supuesto que todo va en Docker, un sencillo Dockerfile, que me permite desplegar el servicio en cualquiera de los servidores que tengo actualmente funcionando.
Por supuesto que la combinación es un docker-compose.yml
en la que va tanto la web app como la base de datos PostgreSQL, y detrás de un proxy inverso como es Traefik para mantener el resto de servicios funcionando.
Conclusión
De vez en cuando, cuando me tropiezo con algún obstáculo, me planteo si la elección de esta combinación Rust + TypeScritp, Axum + React, es la combinación adecuada. Siempre son dudas, porque no hay nadie al otro lado que te diga si vas por el camino adecuado. Este camino de Mamá quiero ser fullstack developer es uno que estoy recorriendo solo, y que se puede hacer solo. Simplemente, que en ocasiones necesitas esa palabra de apoyo, esa recomendación donde te dicen, que si, que ese es el camino.