- Introducción
- Conociendo Reflex
- Frontend
- Backend
- Deploy
- Y así es como conocí Reflex
- Y esto es sólo el principio
- Consideraciones finales
Quizás este título te resulte atrevido, por eso, si me lo permites, me presentaré antes de nada para darte un poco de contexto.
Mi nombre es Brais Moure, soy ingeniero de software desde 2010, freelance desde 2015 y divulgo sobre programación desde finales de 2018.
Lo más importante para este artículo es mi principal actividad profesional como desarrollador: creo apps nativas para iOS y Android.
Es cierto que a lo largo de mi carrera he trabajado en bastantes proyectos web, pero en los últimos años no ha formado parte de mi día a día.
Dicho esto, hace poco más de un año, y sobre todo pensando en la parte del contenido que genero para la comunidad, me propuse retomar la parte de desarrollo web con un lenguaje que últimamente estoy utilizando bastante: Python.
Sobre decir que Python es uno de los lenguajes más demandados en la actualidad, sobre todo en data, IA, scripting y backend… Pero no especialmente en frontend.
Disclaimer: Este artículo puede contener humor. Que nadie se enfade.
Pues justamente al frontend es donde quiero llegar. Y esta es una de las respuestas más repetidas que he encontrado:
NO uses Python en frontend. Usa JavaScript.
Entiendo la premisa. JS es el lenguaje de la web, bla, bla, bla… Pero a mí me gusta Python, y creo que en el año 2024 tenemos que empezar a superar el debate de «mi lenguaje es mejor que el tuyo», cuando todos sabemos que la elección del lenguaje/framework en un equipo o desarrollo está ligada a muchos más motivos más allá de la búsqueda de la perfección tecnológica.
Hoy en día existen infinidad de opciones más que válidas para desarrollar cualquier tipo de software. No te veo usando C para todo, si es que buscas tal «perfección». Todo esto asumiendo que una «buena/mala» elección de stack tecnológico implique que el código que escribamos esté a la altura de nuestra elección.
Por otra parte, existen decenas de opciones para desarrollar front en Python: Django, Flask, Pyramid, Flet, Dash, Gradio, CherryPy, web2py… Pero, sinceramente, y viniendo de un entorno y frameworks actuales, como son los de mobile nativos, mi primera sensación es que se sienten algo así:
(Acuérdate del disclaimer)
Y en este momento volverá la gente que…
- Es que con HTML y CSS…
- Es que con JavaScript…
- Es que con React…
Ya está bien. YO QUIERO USAR PYTHON.
Y ocurrió algo
En diciembre de 2022 apareció un nuevo framework llamado Pynecone, en su versión 0.1.8 Alpha. Cero ruido.
Ya en julio de 2023, con su cambio de nombre a Reflex, y el lanzamiento de su versión 0.2.0, descubrí por primera vez este framework. Y la comunidad comenzó a hablar de él.
(Vamos a añadir que sólo un mes después recibió una ronda de financiación de 5 millones de $ por parte de importantes fondos y empresas de Silicon Valley).
Comencé a leer sobre su uso, y esto fue lo que pasó…
¿Sabes qué es lo primero que se visualiza en la web de Reflex?
Frontend.
Backend.
Deploy.
Pure Python.
No JavaScript required.
¿Alguien ha estado escuchado mis plegarias?
Conociendo Reflex
Reflex es un framework Open Source (con licencia Apache 2.0), 19K estrellas en GitHub y miles de aplicaciones creadas en unos meses (con algunos equipos destacados de empresas como Amazon, NASA, DELL, Samsung, IBM, Nike…).
Y por supuesto, puedes usar cualquier dependencia de Python dentro de su código.
Hasta aquí nada relevante. Como mucho, parece que su desarrollo y adopción pintan bien.
¿Cómo iniciar? Muy fácil.
Unset
$ pip install reflex # Instala la dependencia
$ reflex init # Inicializa el proyecto (existen templates)
$ reflex run # Arranca el server
Vamos a hacer un repaso por las partes más destacadas de Reflex y su peculiar filosofía a la hora de suministrarnos herramientas de desarrollo. A ver si soy capaz de convencerte de por qué surgió el amor entre nosotros.
Frontend
Ya te he presentado la web de Reflex. Por supuesto, está 100% desarrollada usando su propia tecnología.
La filosofía de Reflex es la siguiente: desarrollar un entorno rápido y seguro con Python puro utilizando lo que ya funciona.
¿Eh? Te lo explico.
¿Necesitas empezar a desarrollar tu frontend desde cero? NO.
Reflex cuenta con más de 60 componentes de UI ya creados, temas, modo claro/oscuro, responsive…
¿Te suena la librería de componentes Radix UI?
Es una de las más utilizadas y apoyadas por la comunidad.
Pues Reflex ha creado un «wrapper» (envoltorio/puente) para poder usarla desde su framework Python (cuando originalmente funciona en JS con React).
import reflex as rx
rx.button("Click me")
rx.flex(
rx.button("Enabled"),
rx.button("Disabled", disabled=True),
spacing="2",
)
rx.input(placeholder="Search here...", max_length=20)
rx.list.unordered(
rx.list.item("Example 1"),
rx.list.item("Example 2"),
rx.list.item("Example 3"),
)
Con ese pequeño código (en Python) estarás usando los componentes de Radix en tu frontend. Aquí tienes el listado completo:
¿Y si quiero usar iconos?
¿Conoces Lucide Icons? Otro proyecto muy reconocido.
Así es, Reflex ha implementado su uso con un simple rx.icon.
¿Y gráficas? Pues más de lo mismo con Recharts & Plotly.
def bar_simple():
return rx.recharts.bar_chart(
rx.recharts.bar(
data_key="uv",
stroke=rx.color("accent", 9),
fill=rx.color("accent", 8),
),
rx.recharts.x_axis(data_key="name"),
rx.recharts.y_axis(),
data=data,
width="100%",
height=250,
)
Creo que ya se entiende por dónde quiero ir.
Pero…
¿Y si quiero usar CSS?
Lo puedes utilizar directamente con propiedades en Python, inline o creando tus propios diccionarios como una hoja de estilos (entre otras opciones).
style = {
"font_family": "Comic Sans MS",
"font_size": "16px",
}
app = rx.App(style=style)
rx.text(
"Hello World",
background_image="linear-gradient(271.68deg, #EE756A 0.75%, #756AEE 88.52%)",
background_clip="text",
font_weight="bold",
font_size="2em",
)
¿Y si quiero usar Tailwind?
¡Reflex tiene soporte! Usas su propiedades en el class_name del componente.
rx.box(
"Hello World",
class_name="text-4xl text-center text-blue-500",
)
¿Y si quiero usar html, css o js puro?
No te preocupes. Existen diferentes mecanismos.
# HTML
rx.el.[elemento html]
# CSS
app = rx.App(
stylesheets=[
"/styles.css"
],
)
# JS
rx.script(src="/my-custom.js")
Ya, ya… Pero es que con React…
Cierto, React es uno de los frameworks actuales más usados y potentes para desarrollar frontend con JavaScript. Su importancia es indudable, pero tengo algo que contarte…
import reflex as rx
class Spline(rx.Component):
library = "@splinetool/react-spline"
lib_dependencies: list[str] = [
"@splinetool/runtime@1.5.5"
]
tag = "Spline"
is_default = True
scene: rx.Var[str]
spline = Spline.create
def index():
return spline(scene="https://prod.spline.design/joLpOOYbGL-10EJ4/scene.splinecode")
Efectivamente. Desde Reflex puedes utilizar cualquier biblioteca de React usando Python.
Te acabo de compartir un ejemplo con Spline, una herramienta de renderizado 3D que permite interactuar con los modelos.
Reflex se encargará de instalarla (desde npm) y mapear las propiedades de Python a React y JS.
No me mientas. Esto no te lo esperabas.
La explicación es simple. Nuestro frontend, en última instancia, será JS, HTML y CSS (aunque nosotros lo programemos con Python), ya que son los lenguajes que el explorador web es capaz de entender. Pues bien, para este proceso de transformación, Reflex utiliza React, Next.js y Node.js, tres de los grandes referentes del desarrollo web actual.
¿Para qué reinventar la rueda si ya existen herramientas que funcionan a la perfección, tienen un gran futuro por delante y cuentan con un apoyo masivo de la comunidad?
Sorpresa, estamos usando «lo mejorcito» del desarrollo web desde Python.
Backend
¿No te ha parecido suficiente? No te preocupes. Hay más.
Con Reflex también podremos crear nuestro backend: manejar estados, eventos, routers, generar un API REST, una base de datos local, autenticación… De nuevo, con Python.
Este es un ejemplo simple. Una función index que representa el front, y una clase State que se maneja desde el back.
class State(rx.State):
count: int = 0
def increment(self):
self.count += 1
def decrement(self):
self.count -= 1
def index():
return rx.hstack(
rx.button("Decrement",
on_click=State.decrement,
),
rx.heading(State.count),
rx.button("Increment",
on_click=State.increment,
),
spacing="4",
)
En el momento que se hace click en el botón, se modifica el valor de la variable count, lo que hace variar el estado en el back y repintar su valor en el front. Sin más, así de mágico todo el proceso de comunicación y notificación.
Para crear rutas únicamente añadiremos las funciones asociadas a los componentes visuales.
def index():
return rx.text("Root Page")
def about():
return rx.text("About Page")
def custom():
return rx.text("Custom Route")
app = rx.App()
app.add_page(index)
app.add_page(about)
app.add_page(custom, route="/custom-route")
¿Para una base de datos relacional? Tenemos soporte nativo a un SQLite.
¿No te gusta esta opción? Instalas la dependencia Python de tu BBDD o conector (un MongoDB, por ejemplo), y ya está.
Pero la gran pregunta… ¿Y cómo creo una API REST?
Aquí no tendremos el problema del front. En back podremos ejecutar Python, y para ello vamos a hablar de uno de los frameworks de creación de APIs más famosos de la actualidad, que, casualmente, ya está escrito en Python: FastAPI.
Entiendo… Pero esto es Reflex, no FastAPI.
¿Recuerdas la filosofía del front para usar React?
Pues eso…
async def api_test(item_id: int):
return {"my_result": item_id}
app = rx.App()
app.api.add_api_route("/items/{item_id}", api_test)
En el momento que accedes a app.api, en realidad ya estarás trabajando con la instancia de FastAPI para que hagas uso de ella como gustes.
Deploy
¿No te ha parecido suficiente? Por si te ha parecido poco la posibilidad de desarrollar front y back con este framework, hablemos del despliegue del proyecto.
En primer lugar tenemos que entender que un reflex run corre un servidor con una url por defecto para el front y otra para el back.
Front: localhost:3000
Back: localhost:8000
Es decir, tenemos dos artefactos a desplegar.
El camino fácil y rápido: Hosting Reflex
¿Te he dicho que Reflex tiene su propio hosting y podemos desplegar el proyecto desde el CLI sin configurar nada con dos líneas de código?
reflex login
reflex deploy
Gratis. Más fácil, imposible. Eso sí, no tendrás control sobre la máquina o el despliegue (aunque están trabajando en ello).
Hosting Propietario
¿Quieres desplegar en tu servidor o servicio de hosting? Ningún problema.
reflex export
frontend.zip (static HTML, CSS, JS)
backend.zip (Ptyhon)
Básicamente debes tener en cuenta que el front estará formado por HTML, CSS y JS, y el back por código Python. Con eso, la decisión a nivel de infraestructura es tuya.
Puedes desplegar en front como una web estática y el back en un server Python. O la opción recomendada por Reflex: usar Docker.
Parece que no mentían.
Frontend.
Backend.
Deploy.
Pure Python.
No JavaScript required.
Y así es
Cómo comencé a desarrollar las webs de la comunidad…
(En mi GitHub puedes encontrar el código de alguno de estos proyectos)
Y de esta manera encontré una tecnología con Python que respondía a mis necesidades.
Y esto sólo es el principio
Reflex se encuentra camino a su versión final (sí, a pesar de lo potente y maduro que parece). Y todo esto en poco más de un año.
Por si te interesa, aquí tienes algunos sitios importantes:
Servidor de Discord (donde dan un soporte de 10)
Y muchísimo más en Reflex
Consideraciones finales
Reflex es una opción más. No quiere decir que sea mejor que «tal framework» o que tengas que dejar usar «tal otro». Su propósito es proporcionar un entorno moderno, simple, seguro y rápido de desarrollo web a personas que utilizan Python. Ni más, ni menos.
En mi caso, ha resultado una opción perfecta alineada con mi background y preferencias.
Como siempre, la última palabra la tienes tú. Prueba, saca tus propias conclusiones y respeta las decisiones de los demás.