
Mira el video si prefieres:
Usar Vite con Remix en Cloudflare, es una de las formas más rápidas para publicar un sitio web moderno full stack, hoy en día. ✅
Además de que publicarlo en Cloudflare implica todos los beneficios del Edge. Es decir, en multiples servidores al rededor del mundo gracias a Cloudflare. 🌎
👀 Te dejo un enlace a mi podcast donde te explico qué es The Edge.
Ya con nuestro sitio web rapidísimo corriendo en el Edge, también queremos utilizar PrismaORM con nuestra app, porque es más fácil mantener nuestros tipos y esquemas, de nuestra base de datos MongoDB de toda la vida que tenemos en la nuble de Atlas, empleando Prisma. ▲
El problema es que Prisma no se lleva muy bien con Cloudflare todavía (2024) 😟
Por eso en este video, te voy a enseñar cómo lograr usar tu base de datos MongoDB con Prisma en cloudflare. Lo único que necesitas es ya tener tu *string* de conexión a tu Base de datos en Mongo Atlas
. Si es así, comencemos pues. 👽
👀 A este stack yo le llamo: MRRC (Mongo, Remix, React, Cloudflare)
Creando el proyecto con Remix
Vamos a publicar en una de las nubes Edge más rápidas usando Vite con un plugin llamado Remix.
Para ello vamos a emplear uno de los templates de Remix en el comando:
npx create-remix@latest --template remix-run/remix/templates/cloudflare-workers
Muy bien, ya tenemos un app full stack configurada para trabajar con Cloudflare. 🤯
Ahora, vamos a escribir este componente en app/routes/_index.tsx
que es nuestra home page.
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/cloudflare"; import { useMotionValue, useTransform, motion, useMotionTemplate, } from "framer-motion"; import { MouseEvent } from "react"; import { useLoaderData } from "@remix-run/react"; import { getDb } from "~/db/db.server"; export const meta: MetaFunction = () => { return [ { title: "blissmo test nomás" }, { name: "description", content: "Bienvenido a Remix sobre Cloudflare! por: Fixtergeek.com", }, ]; }; export const loader = async ({ context }: LoaderFunctionArgs) => { const db = getDb(context.cloudflare.env); return { users: await db.user.findMany() }; }; export default function Index() { const { users } = useLoaderData<typeof loader>(); const clientX = useMotionValue(0); const clientY = useMotionValue(0); const xDegs = useTransform(clientY, [0, 500], [25, -25]); const yDegs = useTransform(clientX, [0, 1000], [-25, 25]); return ( <> <motion.div onMouseMove={(e: MouseEvent) => { // bounds.current = e.currentTarget.getBoundingClientRect(); clientX.set(e.clientX); clientY.set(e.clientY); }} className="bg-[#15191f] flex items-center h-screen justify-center" style={{ backgroundImage: useMotionTemplate`radial-gradient(circle at ${clientX}px ${clientY}px, #322d93, transparent 80%)`, }} > <section className=" flex flex-col items-center"> <motion.div style={{ // perspectiveOrigin: "center right", transformStyle: "preserve-3d", perspective: 800, rotateY: yDegs, rotateX: xDegs, }} transition={{ velocity: 0 }} className="text-gray-100" > <button className="hover:scale-105 transition-all active:scale-100"> <img src="https://fixtergeek.com/assets/robot-gradiente.svg" alt="fixtergeek logo" className="w-60 cursor-pointer " /> </button> </motion.div> <h1 className="text-4xl font-bold text-white"> Remix + Cloudflare es la onda 😎 </h1> <a className="underline my-2 text-lg hover:opacity-80 text-[#7871f2] hover:text-white transition-all" target="_blank" rel="noreferrer" href="http://fixtergeek.com/cursos" > Toma un curso de Remix </a> </section> </motion.div> <section className="grid gap-2 grid-cols-4 px-8 mx-auto"> {users.map((user) => ( <button key={user.email} className="truncate py-2 px-4 rounded-xl bg-indigo-100 hover:bg-indigo-300" > {user.email} </button> ))} </section> </> ); }
No te preocupes tanto por todo lo que está ahí, luego lo lees con calma. Es solo para que la página se vea bonis. 🎀
Todavía nos falta crear algunas utilidades como: const db = getDb(context.cloudflare.env);
ahora vamos para allá, primero configuremos Prisma.
Configurando PrismaORM
Vamos a echar a andar nuestra base de datos para que funcione tanto en local para desarrollar como en con Cloudflare en producción y staging. Para ello, vamos a instalar las herramientas e inicializar el schema.
npm i @prisma/client && npm i -D prisma npx prisma init --datasource-provider mongodb
Nuestro archivo de .schema
debería quedar algo así:
// prisma/prisma.schema datasource db { url = env("") provider = "mongodb" } generator client { provider = "prisma-client-js" } model User { id String @id @default(auto()) @map("_id") @db.ObjectId // Específico para MongoDB displayName String? email String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt }
Yo he agregado mi modelo User
, pues mi base de datos ya contiene muchos datos.
Finalmente, vamos a ejecutar un hack para que Prisma logre trabajar con Cloudflare.
Prisma accelerate
Existen varias alternativas de paga para usar nuestra base de datos MongoDB desde el edge, como: directamente en Mongo Atlas con una de sus bases de datos “serverless”. Pero para este video, usaremos la opción gratuita de Prisma Accelerate. ✅
Las bases de datos necesitan cierto tiempo para conectar vía TCP, esto dificulta su uso en el Edge, donde todo es efímero y rapidísimo. Por eso es necesario colocar un Proxy en frente de nuestra base de datos que lidie con esto usando estrategias de cache. Y, eso es lo que precisamente el servicio freemium de Prisma Accelerate hace. Por supuesto que podrías crear tu propio proxy directamente, con NGiNX si fueras curiosa. 🤩
Creamos un nuevo proyecto y pegamos nuestro string de conexión de nuestra base de datos MongoDB y a cambio obtendremos una API Key que usaremos en nuestra app.
Cloudflare no tiene variables globales
Las considera una mala práctica y por esta razón Prisma tiene que instanciarse desde el loader de Remix.
Para eso crearemos esta función dentro dl archivo: db/db.server.ts
. Así, Remix puede separar mejor el código.
// app/db/db.servet.ts import { PrismaClient } from "@prisma/client/edge"; import { withAccelerate } from "@prisma/extension-accelerate"; let db: PrismaClient; declare global { var __db: PrismaClient | undefined; } export function getDb(env) { let options; if (!env.DATABASE_URL) { options = { datasources: { db: { url: "prisma://accelerate.prisma-data.net/?api_key=eyJhbXUs", }, }, }; } else { options = { datasources: { db: { url: env.DATABASE_URL, }, }, }; } if (env.NODE_ENV === "production") { if (!db) db = new PrismaClient(options).$extends(withAccelerate()); } else { if (!global.__db) { global.__db = new PrismaClient(options).$extends(withAccelerate()); } db = global.__db!; } return db; }
Ahora podemos llamar a esta función desde nuestro loader:
// app/routes/_index.tsx import { getDb } from "~/db/db.server"; export const loader = async ({ context }: LoaderFunctionArgs) => { const db = getDb(context.cloudflare.env); return { users: await db.user.findMany() }; };
Listo para producción en el edge con Wrangler
Vamos a probar que nuestra configuración funciona corriendo npm start
, lo que detonará el emulador de wrangler
y correrá nuestro proyecto como si estuviéramos ya en Cloudflare.
"start": "npm run build && wrangler pages dev ./build/client",
Yo suelo agregar el paso del build porque se me olvida. 🤓
Pequeñas modificaciones
Hay que agregar un par de cositas a Vite para evitar algunos bugs conocidos. 📚
Así queda nuestro archivo vite.config
ya con la llave define:{global:{}}
agregada.
import { vitePlugin as remix, cloudflareDevProxyVitePlugin as remixCloudflareDevProxy, } from "@remix-run/dev"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; export default defineConfig({ define: { global: {}, }, server: { port: 3000 }, plugins: [ remixCloudflareDevProxy(), remix({ future: { v3_fetcherPersist: true, v3_relativeSplatPath: true, v3_throwAbortReason: true, }, }), tsconfigPaths(), ], });
Por fin intentamos subir a producción con npm run deploy
.
"deploy": "npx prisma generate --no-engine && npm run build && wrangler pages deploy ./build/client",
Este script también lo modifico un poco para que se genere el build y el cliente de Prisma antes de hacer el deploy. ✅
Tu base de datos ahora funciona en el Edge. 🤯
Abrazo. Bliss. 🤓
Enlaces relacionados

Aprende en 5 minutos qué es HTML y cuando utilizar cada una de sus etiquetas
Checa este otro Post
