¡Hola, desarrolladores web! El año pasado lanzamos una serie de mejoras que facilitaron mucho la implementación de aplicaciones web en Cloudflare, y en respuesta hemos observado un crecimiento espectacular de Astro, Next.js, Nuxt, Qwik, Remix, SolidStart, SvelteKit y otras aplicaciones web alojadas en Cloudflare. Hoy, anunciamos mejoras importantes en nuestra integración con estos marcos web que facilitan el desarrollo de aplicaciones sofisticadas que utilizan D1, nuestra base de datos SQL, nuestro almacén de objetos R2, los modelos de IA y otras funciones avanzadas de la plataforma para desarrolladores de Cloudflare.
En el pasado, si querías desarrollar una aplicación basada en un marco web con D1 y ejecutarla localmente, tenías que crear una versión de producción de tu aplicación, y luego ejecutarla localmente utilizando `wrangler pages dev`. Aunque funcionaba, cada una de tus iteraciones de código tardaba segundos, o decenas de segundos para aplicaciones grandes. La iteración con compilaciones de producción es sencillamente demasiado lenta, te aparta del flujo y no te permite aprovechar todas las optimizaciones DX en las que los autores del marco han trabajado arduamente. ¡Esto va a cambiar a partir de hoy!
Nuestro objetivo es integrarnos con los marcos web de la manera más natural posible, sin que los desarrolladores tengan que aprender y adoptar cambios significativos en el flujo de trabajo o API personalizadas cuando implementen su aplicación en Cloudflare. Tanto si desarrollas en Next.js como en Nuxt, o prefieres otro marco, ahora puedes seguir utilizando el flujo de trabajo de desarrollo local ultrarrápido que conoces, y poner tu aplicación en producción en Cloudflare.
Todos los marcos web integrales vienen con un servidor de desarrollo local (servidor de desarrollo) que está adaptado al marco y que a menudo proporciona una experiencia de desarrollo excelente, con una sola excepción — no es compatible de forma nativa con algunas funciones importantes de la plataforma de desarrollo de Cloudflare, sobre todo, con nuestras soluciones de almacenamiento.
Así que, hasta hace poco, había que tomar una decisión difícil. Podías utilizar el servidor de desarrollo específico del marco para desarrollar tu aplicación, pero renunciar al acceso a muchas de las funciones de Cloudflare o, como alternativa, podías aprovechar al máximo la plataforma de Cloudflare, incluidos varios recursos como D1 o R2, pero tenías que renunciar al uso de las herramientas específicas para desarrolladores del marco. En ese caso, tu ciclo de iteración se ralentizaba, y tardabas segundos en lugar de milisegundos en ver los resultados de los cambios de código en el navegador. ¡Esto se acabó! Echemos un vistazo.
Desarrollemos una aplicación
Vamos a crear una nueva aplicación con C3 (create-cloudflare-cli), nuestra herramienta de línea de comando. Podríamos usar cualquier cliente npm de nuestra elección (¿algún cliente pnpm?), pero para simplificar las cosas en esta publicación, usaremos el cliente npm predeterminado. Para empezar, simplemente ejecuta:
$ npm create cloudflare@latest
Asigna un nombre a tu aplicación o utiliza el nombre generado de forma aleatoria. A continuación, selecciona la categoría "Sitio web o aplicación web " y elige el marco integral que prefieras. Admitimos Astro, Next.js, Nuxt, Qwik, Remix, SolidStart y SvelteKit.
Dado que C3 delega el andamiaje de la aplicación a la última versión de la CLI específica del marco, realizarás el soporte temporal de la aplicación exactamente como pretendían los autores del marco, sin perder ninguna de las funciones u opciones del marco. A continuación, C3 añade a tu aplicación todo lo necesario para la integración y la implementación en Cloudflare para que no tengas que configurarlo tú mismo.
Con el andamiaje de nuestra aplicación, vamos a hacer que muestre una lista de productos almacenados en una base de datos con solo unos pasos. Primero, añadimos la configuración de nuestra base de datos a nuestro archivo de configuración wrangler.toml:
[[d1_databases]]
binding = "DB"
database_name = "blog-products-db"
database_id = "XXXXXXXXXXXXXXXX"
¡Sí, así es! Ahora puedes configurar tus recursos enlazados a través del archivo wrangler.toml, incluso para aplicaciones integrales implementadas en Pages. Compartiremos más información sobre las mejoras de configuración de Pages en una publicación específica.
Ahora vamos a crear un archivo schema.sql sencillo que represente el esquema de nuestra base de datos:
CREATE TABLE products(product_id INTEGER PRIMARY KEY, name TEXT, price INTEGER);
INSERT INTO products (product_id, name, price) VALUES (1, 'Apple', 250), (2, 'Banana', 100), (3, 'Cherry', 375);
E inicializamos nuestra base de datos:
$ npx wrangler d1 execute blog-products-db --local --file schema.sql
Ten en cuenta que hemos utilizado –local
flag of wrangler d1 execute
para aplicar los cambios a nuestra base de datos D1 local. Esta es la base de datos a la que se conectará nuestro servidor de desarrollo.
A continuación, si utilizas TypeScript, informa a TypeScript sobre tu base de datos ejecutando:
$ npm run build-cf-types
Este comando está preconfigurado para todas las aplicaciones integrales creadas a través de C3 y ejecuta wrangler types
para actualizar la interfaz del entorno de Cloudflare que contiene todos los enlaces configurados.
Ahora podemos iniciar el servidor de desarrollo proporcionado por tu marco a través de un acceso directo muy útil:
$ npm run dev
Este acceso directo iniciará el servidor de desarrollo de tu infraestructura, ya sea con next dev, nitro o vite.
Ahora para acceder a nuestra base de datos y enumerar los productos, podemos utilizar un enfoque específico del marco. Por ejemplo, en una aplicación Next.js que utiliza el enrutador App, podríamos actualizar aplicación/api/hello/route.ts
con lo siguiente:
const db = getRequestContext().env.DB;
const productsResults = await db.prepare('SELECT * FROM products').all();
return Response.json(productsResults.results);
O en una aplicación Nuxt, podemos crear un archivo server/api/hello.ts
y rellenarlo con:
export default defineEventHandler(async ({ context }) => {
const db = context.cloudflare.env.DB;
const productsResults = await db.prepare('SELECT * FROM products').all();
return productsResults.results;
});
Suponiendo que el servidor de desarrollo del marco se ejecuta en el puerto 3000, puedes probar la nueva ruta de la API en cualquiera de los marcos explorando http://localhost:3000/api/hello. Para simplificar, elegimos rutas para la API en estos ejemplos, pero lo mismo se aplica a cualquier ruta que genere la IU.
Cada marco web tiene su propia forma de definir rutas y pasar información contextual sobre la solicitud a través de la aplicación, por lo que la forma en que accedes a tus bases de datos, almacenes de objetos y otros recursos dependerá de tu marco. Puedes leer nuestras guías actualizadas de marcos integrales para obtener más información:
Ahora que sabes cómo acceder a los recursos de Cloudflare en el marco de tu elección, todo lo demás que sabes sobre tu marco sigue igual. Ya puedes desarrollar tu aplicación localmente, utilizando el servidor de desarrollo optimizado para tu marco, compatibilidad con el reemplazo de módulos en caliente (HMR), herramientas de desarrollo personalizadas, compatibilidad mejorada con la depuración y mucho más, todo ello sin dejar de beneficiarte de las API y funciones específicas de Cloudflare. ¡Todos salimos ganando!
¿Qué ha cambiado realmente para permitir estos flujos de trabajo de desarrollo?
Para disminuir la latencia de desarrollo y preservar las experiencias específicas de los marcos personalizados, necesitábamos permitir que los marcos web y sus servidores de desarrollo se integraran con wrangler y miniflare de forma eficaz, de forma casi imperceptible.
Miniflare es un componente clave en este rompecabezas. Es nuestro simulador local para recursos específicos de Cloudflare, que funciona con workerd, nuestro entorno de ejecución de JavaScript (JS). Con el uso de workerd, nos aseguramos de que las API de JavaScript de Cloudflare se ejecuten de manera local de una forma que simule fielmente nuestro entorno de producción. El problema es que los servidores de desarrollo del marco ya dependen de Node.js para ejecutar la aplicación, por lo que añadir otro entorno de ejecución JS quebranta muchas suposiciones sobre cómo se han diseñado estos servidores de desarrollo.
Sin embargo, nuestro equipo ideó un enfoque interesante para acercar estos dos entornos de ejecución JS. La llamamos la API getPlatformProxy(), que ahora forma parte de wrangler y funciona con el proxy mágico de miniflare. Esta API expone un objeto proxy JS que se comporta igual que el objeto env habitual de Workers que contiene todos los recursos enlazados. El objeto proxy permite que el código de Node.js invoque de forma transparente el código JavaScript que se ejecuta en workerd, y acceder a las API específicas del entorno de ejecución de Cloudflare.
Con este puente entre los entornos de ejecución de Node.js y workerd, tu aplicación ahora puede acceder a los simuladores de Cloudflare para D1, R2, KV y otras soluciones de almacenamiento directamente mientras se ejecuta en un servidor de desarrollo con tecnología de Node.js. O incluso podrías escribir un script Node.js para hacer lo mismo:
import {getPlatformProxy} from 'wrangler';
const {env} = getPlatformProxy();
console.dir(env);
const db = env.DB;
// Now let’s execute a DB query that runs in a local D1 db
// powered by miniflare/workerd and access the result from Node.js
const productsResults = await db.prepare('SELECT * FROM products').all();
console.log(productsResults.results);
Con la API getPlatformProxy()
disponible, el trabajo pendiente consistía en actualizar todos los adaptadores del marco, los complementos y, en algunos casos, los propios marcos para hacer uso de esta API. Agradecemos la ayuda que hemos recibido de los equipos de marcos en este recorrido, especialmente de Alex de Astro, pi0 de Nuxt, Pedro de Remix, Ryan de Solid, Ben y Rich de Svelte, y de nuestro colaborador en el proyecto next-on-pages, James Anderson.
Mejoras futuras de los flujos de trabajo de desarrollo con Vite
Aunque la API getPlatformProxy()
es una buena solución para muchos escenarios, podemos hacerlo mejor. Si pudiéramos ejecutar toda la aplicación en nuestro entorno de ejecución JS en lugar de Node.js, podríamos simular aún más fielmente el entorno de producción y reducir el conflicto con los desarrolladores y las sorpresas de producción.
En un mundo ideal, nos gustaría que desarrollaras en el mismo entorno de ejecución que implementas en producción, y esto solo se puede lograr integrando workerd directamente en los servidores de desarrollo de todos los marcos, lo cual no es baladí teniendo en cuenta el número de marcos y las diferencias entre ellos.
Sin embargo, tuvimos un poco de suerte. Cuando pusimos en marcha esta iniciativa, nos dimos cuenta rápidamente de que Vite, un popular servidor de desarrollo utilizado por muchos marcos integrales, estaba ganando cada vez más adeptos. De hecho, Remix ha cambiado recientemente a Vite y ha confirmado la popularidad de Vite como la base común para el desarrollo web actual.
Si Vite ofreciera soporte de primera clase para ejecutar una aplicación integral en un entorno de ejecución de JavaScript alternativo, podríamos permitir que cualquier usuario de Vite desarrollara sus aplicaciones localmente con acceso completo a la plataforma para desarrolladores de Cloudflare. Se acabaron las soluciones e integraciones personalizadas específicas del marco. Todos los desarrolladores pueden acceder ya a las funciones de un marco integral, Vite y Cloudflare.
¿Suena demasiado bueno para ser verdad? Tal vez. Estamos encantados de trabajar con el equipo de Vite en la propuesta de entornos de Vite, que podría permitir precisamente eso. Seguimos trabajando en la propuesta, así que no te pierdas las novedades.
¿Qué vas a desarrollar?
Nuestro objetivo es que Cloudflare sea la mejor plataforma de desarrollo para los desarrolladores web. Agilizar y facilitar el desarrollo de tu aplicación con marcos y herramientas con los que ya estás familiarizado es una parte importante de nuestra historia. Empieza tu recorrido con nosotros ejecutando un solo comando:
$ npm create cloudflare@latest