Remix

¿Es Remix JS el Próximo Framework Para Ti?

Facundo Giuliani
Facundo Giuliani

En el mundo del desarrollo web, y de la tecnología en general, nuevas herramientas aparecen cada vez más seguido. Si bien muchas son bastante similares entre sí, o comparten los mismos propósitos, son las que ofrecen un punto de vista diferencial las que logran hacerse masivas y popularizarse entre los miembros de la comunidad web. Si hablamos de frameworks, y más específicamente los que se basan en React, podemos ver que Remix ha estado sonando fuerte en los últimos meses.

Pero, ¿A que se debe esto? En este artículo veremos algunas de las razones.

¿Que es Remix?

Según su sitio web oficial, Remix es un framework full stack que nos permite focalizarnos en las interfaces de usuario, y seguir los estándares web para crear experiencias de usuario rápidas y resilientes. Con Remix podemos crear tanto el frontend como el backend de nuestras aplicaciones web, utilizando React como base. Entonces, podemos crear componentes React y reglas de renderizado de HTML para nuestro frontend, así como programar rutas manejables en nuestro backend para crear reglas y lógica de negocio.

A diferencia del comportamiento "común" de React, Remix utiliza server-side rendering para manipular los datos y renderizar el contenido y markup HTML en el servidor, enviando la menor cantidad posible de código JavaScript al cliente. Como el framework está construido sobre la Web Fetch API, en lugar de Node, los proyectos creados utilizando Remix pueden correr en cualquier plataforma.

Si bien Remix fue creado hace ya un tiempo, ha ganado más popularidad en los últimos meses porque anteriormente había que pagar una licencia para poder usarlo, y ahora fue lanzado como un proyecto open-source bajo la licencia MIT.

Características de Remix

Entre los distintos beneficios que nos ofrece Remix, podemos destacar:

  • Rutas: En Remix podemos crear archivos JavaScript o TypeScript que utilizaremos para manejar y renderizar una ruta (o varias). Si bien el concepto de rutas no es nuevo, en Remix podemos crear páginas y URLs para ellas de manera sencilla, manejando de manera correcta los nombres de los ficheros y carpetas de nuestro proyecto.

  • Páginas y componentes anidados: Además de manejar rutas, y ofrecernos enrutamiento dinámico, Remix nos brinda otro diferencial: Rutas anidadas. Podemos crear un fichero llamado, por ejemplo, home.jsx y, al mismo nivel en la estructura de archivos, crear una carpeta llamada home. Todos los archivos JavaScript que creemos dentro de esta carpeta serán tratados como componentes anidados dentro de la página generada por home.jsx. Para ello, Remix provee un componente <Outlet /> que usaremos en nuestra página padre para definir donde queremos renderizar los componentes anidados.

  • Loaders y Actions: Como Remix se focaliza en server-side rendering, tenemos a disposición funciones que nos permitirán crear contenido dinámico en el servidor. La función loadermaneja las llamadas a nuestras rutas que se realizan utilizando el verbo HTTP GET, y se utiliza principalmente para obtener datos de alguna fuente. La función action controla las llamadas POST, PUT, DELETE y PATCH, y se utiliza para modificar o mutar datos.

  • Manejo de errores: Si se genera un error en un componente o página anidada, solo fallará el renderizado de ese componente, en lugar de mostrar un error en la página completa.

  • Formularios: Remix utiliza los métodos tradicionales para el manejo de formularios. En lugar de recurrir a JavaScript para el manejo de formularios, podemos utilizar métodos nativos como PUT o POST.

¿En que se diferencia Remix de Next.js?

A simple vista, Remix y Next.js pueden parecer bastante similares. Ambos frameworks fueron creados y funcionan sobre React, y nos ofrecen server-side rendering para generar contenido y markup del lado del servidor, y posteriormente enviarlo al cliente.

Una de las diferencias entre ambos es que Next.js ofrece la posibilidad de crear contenido de manera estática en tiempo de compilación (static site generation), mientras que Remix no ofrece esta posibilidad porque se focaliza en la generación de contenido dynámico del lado del servidor.

Por otro lado, si bien Remix está construido para funcionar sobre React, el framework intenta alejarse un poco del paradigma client side que React nos fuerza a usar, manejando otro tipo de abstracciones.

Y, como dijimos antes, Remix está construido sobre la Web Fetch API en lugar de Node. Esto nos permite correr aplicaciones Remix en servidores Node.js como Vercel, Netlify, u otros, como así también en entornos que no corren sobre Node.js, como Deno Deploy y Cloudflare Workers.

Puedes leer más diferencias entre ambos frameworks en este artículo escrito por Ryan Florence, uno de los co-fundadores de Remix.

Crear una aplicación con Remix

Vamos a crear una aplicación simple para probar las distintas funcionalidades de Remix que mencionamos anteriormente. Para ello, primero ejecutaremos este comando NPM que genera la estructura básica de una aplicación Remix.

npx create-remix

Al ejecutar la línea anterior, la consola nos preguntará como queremos llamar al proyecto y la carpeta que lo contendrá. Después de eso, tendremos la opción de elegir una estructura para una aplicación Remix básica (Just the basics) o si queremos crear un proyecto con una configuración de distintas herramientas y frameworks lista para correr en producción (A pre-configured stack ready for production). En Remix, estas configuraciones son llamadas Stacks. Para nuestro ejemplo elegiremos la opción de un a aplicación básica. Si quieres leer más sobre Remix Stacks, puedes hacerlo en esta guía oficial.

Como bien dijimos antes, las aplicaciones creadas con Remix pueden correr sobre cualquier servidor. Al momento de crear la estructura básica de nuestro proyecto, Remix nos pregunta en que plataforma pensamos desplegar el proyecto que estamos por crear. Si no queremos definir eso ahora mismo, podemos elegir la opción Remix App Server. Remix también nos preguntará si queremos crear un proyecto JavaScript o uno TypeScript. Para nuestro tutorial, crearemos una aplicación JavaScript.

Una vez que todas las tareas fueron ejecutadas y nuestro proyecto fue creado, inspeccionemos un poco como está conformado. A simple vista, las carpetas y archivos nos pueden sonar similares a aplicaciones creadas con otros frameworks. Focalicémonos en la carpeta app, que es donde la mayoría del código de nuestra aplicación va a estar alojado:

  • routes: En esta carpeta vamos a encontrar todos los ficheros que van a manejar las distintas rutas, páginas y elementos anidados de nuestra aplicación.

  • styles: Aquí encontraremos los estilos que utilizaremos en el contenido HTML de nuestras páginas.

  • entry.client.jsx: Este archivo contiene el punto de inicio de nuestra aplicación del lado del cliente, con lógica que va a modificar el DOM de nuestras páginas, basándose en el contenido HTML generado por el servidor.

  • entry.server.jsx: A diferencia del archivo anterior, aquí tendremos lógica que se ejecutará al inicio de nuestra aplicación, en el servidor.

  • root.jsx: Este fichero es el análogo al archivo App.jsx en una aplicación típica de React. Es el punto por defecto de nuestro sitio, el lugar donde definiremos la lógica que queremos usar para la página de inicio del proyecto.

Si ejecutamos npm run dev en la consola, vamos a correr el servidor de desarrollo, y visitando localhost:3000 en el navegador podremos visitar nuestra aplicación de prueba.

Si revisamos el código del archivo root.jsx vamos a ver que el componente <Outlet /> está presente. Esto significa que todas las rutas que vayamos a manipular en nuestro proyecto van a estar contenidas dentro del cuerpo de la página generada por este archivo. Como en Remix se puede trabajar con varios niveles de indentación, vamos a poder crear más componentes <Outlet /> en otras rutas y manejar distintos niveles de renderizado.

Hagamos algunos cambios a esta aplicación, para probar más cosas del framework. Abramos el archivo app/routes/index.jsx y cambiemos su código por este otro.

import { json } from "@remix-run/node";
import { Link, useLoaderData } from "@remix-run/react";
export let loader = () => {
let data = [
{
name: "Argentina",
url: "argentina",
},
{
name: "Chile",
url: "chile",
},
{
name: "Colombia",
url: "colombia",
},
{
name: "Ecuador",
url: "ecuador",
},
];
return json(data);
};
export default function Index() {
let data = useLoaderData();
return (
<main>
<h2>¡Hola!</h2>
<p>¿Desde que país nos visitas?</p>
<ul>
{data.map((country) => (
<li key={country.url}>
<Link to={`country/${country.url}`} prefetch="intent">
{country.name}
</Link>
</li>
))}
</ul>
</main>
);
}

Aquí podemos ver como estamos usando distintas características de Remix:

  • La función loader nos permite capturar los llamados GET a nuestra ruta y, en base a eso, obtener datos que serán usados al momento de renderizar el contenido de la página.

  • Con el mismo objetivo, en Index utilizamos la función useLoaderData para obtener los datos generados por loader.

  • Dentro de Index ejecutamos el código que generará el contenido HTML de nuestra página. Podemos crear y utilizar componentes React, o agregar la lógica directamente dentro de esta función.

Ahora, dentro de root creemos una carpeta llamada country y, dentro de la misma, un archivo llamado $country.jsx:

import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
export const loader = async ({ params }) => {
const country = params.country ?? "error";
return json(country);
};
export default function Country() {
let country = useLoaderData();
return (
<main>
<h2>¡Hola {country.charAt(0).toUpperCase() + country.slice(1)}!</h2>
</main>
);
}

Como podemos ver, el archivo es una ruta dinámica que manejará todos los pedidos que se hagan a una URL con formato country/[país]. Dentro de este fichero utilizamos funciones que también usamos en index.jsx. La función loader a su vez obtiene parámetros del pedido que se está realizando, como country, que proviene de la URL de la página requerida. useLoaderData obtiene el país correspondiente, y la función Country renderiza un saludo para la gente de ese país. ** Te invitamos a que sigas jugando con este proyecto de ejemplo, expandiendo sus funcionalidades, utilizando otras características provistas por Remix.

Conclusión

A lo largo de este artículo pudimos aprender sobre Remix, que es, que características ofrece y cuales son sus ventajas comparado con otros frameworks basados en React. Hicimos una comparación detallada con Next.js, un framework distinto pero con algunos puntos en común. Finalmente vimos como utilizar las características principales de Remix creando un proyecto de ejemplo.

¿Quieres mejorar tus habilidades de frontend?