Hay muchas formas de almacenar los datos en sus aplicaciones. Por ejemplo, en las aplicaciones Cloudflare Workers, tenemos Workers KV para el almacenamiento de valores clave y Durable Objects para el almacenamiento coordinado en tiempo real sin poner en riesgo la consistencia. Fuera del ecosistema de Cloudflare, también puede conectar otras herramientas, tales como NoSQL y bases de datos de gráficos.
Sin embargo, a veces quiere SQL. Los índices permiten recuperar datos rápidamente. Las combinaciones nos permiten describir relaciones complejas entre diferentes tablas. SQL describe de manera declarativa cómo se validan, crean y consultan los datos de nuestra aplicación.
D1 se lanzó hoy en open alpha y, para celebrarlo, quiero compartir mi experiencia en la creación de aplicaciones con D1: específicamente, cómo comenzar y por qué estoy emocionado de que D1 se una a la larga lista de herramientas que puede usar para crear aplicaciones en Cloudflare.
D1 es notable porque es un valor agregado instantáneo para las aplicaciones sin necesidad de nuevas herramientas o salir del ecosistema de Cloudflare. Usando wrangler, podemos hacer desarrollo local en nuestras aplicaciones de Trabajadores, y con la adición de D1 en wrangler, ahora también podemos desarrollar aplicaciones con estado apropiadas localmente. Luego, cuando llega el momento de implementar la aplicación, Wrangler nos permite acceder y ejecutar comandos en su base de datos D1, así como en su propia API.
En esta publicación del blog, te mostraré cómo utilizar D1 para añadir comentarios a un blog estático. Para ello, crearemos una nueva base de datos D1 y una sencilla API JSON que permita la creación y la recuperación de comentarios.
Como mencioné, separar D1 de la aplicación en sí, una API y una base de datos que permanece separada del sitio estático, nos permite extraer las piezas estáticas y dinámicas de nuestro sitio web uno del otro. También facilita la implementación de nuestra aplicación: implementaremos la interfaz en Cloudflare Pages y la API con tecnología D1 en Cloudflare Workers.
Luego, en src/index.ts, inicializaremos una nueva aplicación Hono y definiremos algunos puntos de conexión: GET /API/posts/:slug/comments, and POST /get/api/:slug/comments.
\n
$ npm install hono
\n
Ahora, crearemos una base de datos D1. En Wrangler 2, hay soporte para el subcomando wrangler d1, que le permite crear y consultar sus bases de datos D1 directamente desde la línea de comandos. Entonces, por ejemplo, podemos crear una nueva base de datos con un solo comando:
\n
import { Hono } from 'hono'\nimport { cors } from 'hono/cors'\n\nconst app = new Hono()\n\napp.get('/api/posts/:slug/comments', async c => {\n // do something\n})\n\napp.post('/api/posts/:slug/comments', async c => {\n // do something\n})\n\nexport default app
\n
Con nuestra base de datos creada, podemos tomar el ID del nombre de la base de datos y asociarlo con un enlace dentro de wrangler.toml, el archivo de configuración de wrangler. Los enlaces nos permiten acceder a los recursos de Cloudflare, como bases de datos D1, espacios de nombres KV y depósitos R2, usando un nombre de variable simple en nuestro código. A continuación, crearemos el enlace DB y lo utilizaremos para representar nuestra nueva base de datos:
\n
$ wrangler d1 create d1-example
\n
Tenga en cuenta que esta directiva, el campo [[d1_databases]], actualmente requiere una versión beta de wrangler. Puede instalar esto para su proyecto usando el comando npm install -D wrangler/beta.
\n
[[ d1_databases ]]\nbinding = "DB" # i.e. available in your Worker on env.DB\ndatabase_name = "d1-example"\ndatabase_id = "4e1c28a9-90e4-41da-8b4b-6cf36e5abb29"
\n
Con la base de datos configurada en nuestro wrangler.toml, podemos comenzar a interactuar con él desde la línea de comando y dentro de nuestra función Workers.
Primero, puede emitir comandos SQL directos al usar wrangler d1 execute:
También puede pasar un archivo SQL, lo que es perfecto para la propagación de datos iniciales en un solo comando. Cree src/schema.sql, lo que creará una nueva tabla de comentarios para nuestro proyecto:
\n
$ wrangler d1 execute d1-example --command "SELECT name FROM sqlite_schema WHERE type ='table'"\nExecuting on d1-example:\n┌─────────────────┐\n│ name │\n├─────────────────┤\n│ sqlite_sequence │\n└─────────────────┘
\n
Con el archivo creado, ejecute el archivo de esquema contra la base de datos D1 y páselo con la marca --file:
\n
drop table if exists comments;\ncreate table comments (\n id integer primary key autoincrement,\n author text not null,\n body text not null,\n post_slug text not null\n);\ncreate index idx_comments_post_id on comments (post_slug);\n\n-- Optionally, uncomment the below query to create data\n\n-- insert into comments (author, body, post_slug)\n-- values ("Kristian", "Great post!", "hello-world");
\n
Hemos creado una base de datos SQL con solo algunos comandos y la hemos propagado con datos iniciales. Ahora podemos agregar una ruta a nuestra función de Workers para recuperar datos de esa base de datos. Según nuestra configuración wrangler.toml, ahora se puede acceder a la base de datos D1 a través del enlace DB. En nuestro código, podemos usar el enlace para preparar declaraciones SQL y ejecutarlas, por ejemplo, para recuperar comentarios:
En esta función, aceptamos un parámetro de consulta de URL slug y configuramos una nueva instrucción SQL donde seleccionamos todos los comentarios con un valor post_slug que coincide con nuestro parámetro de consulta. Luego podemos devolverlo como una JSON response.
\n
app.get('/api/posts/:slug/comments', async c => {\n const { slug } = c.req.param()\n const { results } = await c.env.DB.prepare(`\n select * from comments where post_slug = ?\n `).bind(slug).all()\n return c.json(results)\n})
\n
Hasta ahora, hemos creado acceso de solo lectura a nuestros datos. Sin embargo, por supuesto, también es posible "insertar" valores en SQL. Así que definamos otra función que permita hacer un POST a un punto de conexión para crear un nuevo comentario:
En este ejemplo, creamos una API de comentarios para impulsar un blog. Para ver la fuente de esta API de comentarios basada en D1, puede visitar cloudflare/templates/worker-d1-api.
\n
app.post('/API/posts/:slug/comments', async c => {\n const { slug } = c.req.param()\n const { author, body } = await c.req.json<Comment>()\n\n if (!author) return c.text("Missing author value for new comment")\n if (!body) return c.text("Missing body value for new comment")\n\n const { success } = await c.env.DB.prepare(`\n insert into comments (author, body, post_slug) values (?, ?, ?)\n `).bind(author, body, slug).run()\n\n if (success) {\n c.status(201)\n return c.text("Created")\n } else {\n c.status(500)\n return c.text("Something went wrong")\n }\n})
Una de las cosas más emocionantes de D1 es la oportunidad de aumentar las aplicaciones o sitios web existentes con los datos relacionales dinámicos. Como antiguo desarrollador de Ruby on Rails, una de las cosas que más echo de menos de ese marco en el mundo de JavaScript y las herramientas de desarrollo sin servidor es la capacidad de activar rápidamente aplicaciones completas basadas en datos, sin tener que ser un experto en la gestión de la infraestructura de bases de datos. Con D1 y su fácil acceso a datos basados en SQL, podemos crear verdaderas aplicaciones basadas en datos sin comprometer el rendimiento o la experiencia del desarrollador.
Este cambio corresponde muy bien con la llegada de los sitios estáticos en los últimos años, utilizando herramientas como Hugo o Gatsby. Un blog construido con un generador de sitios estáticos como Hugo tiene un rendimiento increíble: se creará en segundos con activos pequeños.
Sin embargo, al cambiar una herramienta como WordPress por un generador de sitios estáticos, pierde la oportunidad de agregar información dinámica a su sitio. Muchos desarrolladores han solucionado este problema al agregar más complejidad a sus procesos de compilación: obteniendo y recuperando datos y generando páginas al utilizar esos datos como parte del desarrollo.
Esta adición de complejidad en el proceso de desarrollo intenta corregir la falta de dinamismo en las aplicaciones, pero aún no es genuinamente dinámica. En lugar de poder recuperar y mostrar nuevos datos a medida que se crean, la aplicación se reconstruye y vuelve a implementar cada vez que los datos cambian para que parezca una representación dinámica y en vivo de los datos. Su aplicación puede permanecer estática y los datos dinámicos vivirán geográficamente cerca de los usuarios de su sitio, accesibles a través de una API consultable y expresiva.
"],"published_at":[0,"2022-11-16T14:00:00.000+00:00"],"updated_at":[0,"2024-10-09T23:21:08.539Z"],"feature_image":[0,"https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3dYVDokYcztYm7vfUlV2gg/767d699e8db4d6c24175d097c9d8c791/making-static-sites-dynamic-with-cloudflare-d1.png"],"tags":[1,[[0,{"id":[0,"2xCnBweKwOI3VXdYsGVbMe"],"name":[0,"Developer Week"],"slug":[0,"developer-week"]}],[0,{"id":[0,"4HIPcb68qM0e26fIxyfzwQ"],"name":[0,"Desarrolladores"],"slug":[0,"developers"]}],[0,{"id":[0,"5cye1Bh5KxFh3pKSnX8Dsy"],"name":[0,"Serverless"],"slug":[0,"serverless"]}],[0,{"id":[0,"7lB8a8hOPXzjt99X5Ye9wb"],"name":[0,"Storage"],"slug":[0,"storage"]}],[0,{"id":[0,"6hbkItfupogJP3aRDAq6v8"],"name":[0,"Cloudflare Workers"],"slug":[0,"workers"]}],[0,{"id":[0,"UKt2GEAUQsbObsNqZ3Pr7"],"name":[0,"D1 (ES)"],"slug":[0,"d1"]}],[0,{"id":[0,"3JAY3z7p7An94s6ScuSQPf"],"name":[0,"Plataforma para desarrolladores"],"slug":[0,"developer-platform"]}]]],"relatedTags":[0],"authors":[1,[[0,{"name":[0,"Kristian Freeman"],"slug":[0,"kristian"],"bio":[0,"Manager, Developer Advocacy team at Cloudflare. We help developers build amazing apps on Cloudflare, with tools like Workers, Pages, and more!"],"profile_image":[0,"https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3VUYoHwDSenpoOr2qQ5rQe/5aae862918663bc3e682ede2eb385c22/kristian.jpg"],"location":[0,"Austin, TX"],"website":[0,"https://www.signalnerve.com"],"twitter":[0,"@kristianf_"],"facebook":[0,null]}]]],"meta_description":[0,"In this blog post, I'll show you how to use D1 to add comments to a static blog site. To do this, we'll construct a new D1 database and build a simple JSON API that allows the creation and retrieval of comments."],"primary_author":[0,{}],"localeList":[0,{"name":[0,"Making static sites dynamic with Cloudflare D1 Config"],"enUS":[0,"English for Locale"],"zhCN":[0,"Translated for Locale"],"zhHansCN":[0,"No Page for Locale"],"zhTW":[0,"Translated for Locale"],"frFR":[0,"Translated for Locale"],"deDE":[0,"Translated for Locale"],"itIT":[0,"No Page for Locale"],"jaJP":[0,"Translated for Locale"],"koKR":[0,"No Page for Locale"],"ptBR":[0,"Translated for Locale"],"esLA":[0,"No Page for Locale"],"esES":[0,"Translated for Locale"],"enAU":[0,"No Page for Locale"],"enCA":[0,"No Page for Locale"],"enIN":[0,"No Page for Locale"],"enGB":[0,"No Page for Locale"],"idID":[0,"No Page for Locale"],"ruRU":[0,"No Page for Locale"],"svSE":[0,"No Page for Locale"],"viVN":[0,"No Page for Locale"],"plPL":[0,"No Page for Locale"],"arAR":[0,"No Page for Locale"],"nlNL":[0,"No Page for Locale"],"thTH":[0,"No Page for Locale"],"trTR":[0,"No Page for Locale"],"heIL":[0,"No Page for Locale"],"lvLV":[0,"No Page for Locale"],"etEE":[0,"No Page for Locale"],"ltLT":[0,"No Page for Locale"]}],"url":[0,"https://blog.cloudflare.com/making-static-sites-dynamic-with-cloudflare-d1"],"metadata":[0,{"title":[0,"Convierte los sitios estáticos en dinámicos con Cloudflare D1"],"description":[0,"In this blog post, I'll show you how to use D1 to add comments to a static blog site. To do this, we'll construct a new D1 database and build a simple JSON API that allows the creation and retrieval of comments."],"imgPreview":[0,"https://cf-assets.www.cloudflare.com/zkvhlag99gkb/AHR3WMjOLSQSNdgHLQ5Kb/a2c7f819a3cdeb37055252c5cd49a481/making-static-sites-dynamic-with-cloudflare-d1-kmNXNe.png"]}]}],"locale":[0,"es-es"],"translations":[0,{"posts.by":[0,"De:"],"footer.gdpr":[0,"RGPD"],"lang_blurb1":[0,"Esta publicación también está disponible en {lang1}."],"lang_blurb2":[0,"Esta publicación también está disponible en {lang1} y {lang2}."],"lang_blurb3":[0,"Esta publicación también está disponible en {lang1}, {lang2} y {lang3}."],"footer.press":[0,"Prensa"],"header.title":[0,"Blog de Cloudflare"],"search.clear":[0,"Borrar"],"search.filter":[0,"Filtrar"],"search.source":[0,"Fuente"],"footer.careers":[0,"Empleo"],"footer.company":[0,"Empresa"],"footer.support":[0,"Asistencia"],"footer.the_net":[0,"theNET"],"search.filters":[0,"Filtros"],"footer.our_team":[0,"Nuestro equipo"],"footer.webinars":[0,"Seminarios web"],"page.more_posts":[0,"Más publicaciones"],"posts.time_read":[0,"{time} min de lectura"],"search.language":[0,"Idioma"],"footer.community":[0,"Comunidad"],"footer.resources":[0,"Recursos"],"footer.solutions":[0,"Soluciones"],"footer.trademark":[0,"Marca"],"header.subscribe":[0,"Suscribirse"],"footer.compliance":[0,"Conformidad"],"footer.free_plans":[0,"Planes gratuitos"],"footer.impact_ESG":[0,"Impact/ESG"],"posts.follow_on_X":[0,"Síguenos en X"],"footer.help_center":[0,"Centro de ayuda"],"footer.network_map":[0,"Mapa de red"],"header.please_wait":[0,"Un momento..."],"page.related_posts":[0,"Publicaciones relacionadas"],"search.result_stat":[0,"Resultados {search_range} de {search_total} para {search_keyword}"],"footer.case_studies":[0,"Casos prácticos"],"footer.connect_2024":[0,"Connect 2024"],"footer.terms_of_use":[0,"Condiciones de uso"],"footer.white_papers":[0,"Notas técnicas"],"footer.cloudflare_tv":[0,"Cloudflare TV"],"footer.community_hub":[0,"Foro de comunidad"],"footer.compare_plans":[0,"Comparar planes"],"footer.contact_sales":[0,"Comunícate con el departamento de ventas"],"header.contact_sales":[0,"Comunícate con el departamento de ventas"],"header.email_address":[0,"Dirección de correo electrónico"],"page.error.not_found":[0,"Página no encontrada"],"footer.developer_docs":[0,"Documentación para desarrolladores"],"footer.privacy_policy":[0,"Política de privacidad"],"footer.request_a_demo":[0,"Solicita una demostración"],"page.continue_reading":[0,"Seguir leyendo"],"footer.analysts_report":[0,"Informes de analistas"],"footer.for_enterprises":[0,"Para empresas"],"footer.getting_started":[0,"Primeros pasos"],"footer.learning_center":[0,"Centro de aprendizaje"],"footer.project_galileo":[0,"Proyecto Galileo"],"pagination.newer_posts":[0,"Publicaciones más recientes"],"pagination.older_posts":[0,"Publicaciones anteriores"],"posts.social_buttons.x":[0,"Comenta en X"],"search.icon_aria_label":[0,"Buscar"],"search.source_location":[0,"Origen/Ubicación"],"footer.about_cloudflare":[0,"Acerca de Cloudflare"],"footer.athenian_project":[0,"Proyecto Athenian"],"footer.become_a_partner":[0,"Ser socio"],"footer.cloudflare_radar":[0,"Cloudflare Radar"],"footer.network_services":[0,"Servicios de red"],"footer.trust_and_safety":[0,"Confianza y seguridad"],"header.get_started_free":[0,"Empieza ya de forma gratuita"],"page.search.placeholder":[0,"Buscar en Cloudflare"],"footer.cloudflare_status":[0,"Estado de Cloudflare"],"footer.cookie_preference":[0,"Preferencias de cookies"],"header.valid_email_error":[0,"Debe ser un correo electrónico válido."],"search.result_stat_empty":[0,"Resultados {search_range} de {search_total}"],"footer.connectivity_cloud":[0,"Conectividad cloud"],"footer.developer_services":[0,"Servicios para desarrolladores"],"footer.investor_relations":[0,"Relaciones con inversores"],"page.not_found.error_code":[0,"Código de error: 404"],"search.autocomplete_title":[0,"Inserta una consulta. Pulsa Intro para enviarla."],"footer.logos_and_press_kit":[0,"Logotipos y dossier de prensa"],"footer.application_services":[0,"Servicios para aplicaciones"],"footer.get_a_recommendation":[0,"Sugerencias"],"posts.social_buttons.reddit":[0,"Comenta en Reddit"],"footer.sse_and_sase_services":[0,"Servicios SSE y SASE"],"page.not_found.outdated_link":[0,"Puede que tengas un enlace obsoleto o que hayas escrito la dirección incorrectamente."],"footer.report_security_issues":[0,"Informar sobre problemas de seguridad"],"page.error.error_message_page":[0,"Lamentablemente, no podemos encontrar la página que buscas."],"header.subscribe_notifications":[0,"Suscríbete para recibir notificaciones de nuevas publicaciones:"],"footer.cloudflare_for_campaigns":[0,"Cloudflare for Campaigns"],"header.subscription_confimation":[0,"Suscripción confirmada. ¡Gracias por suscribirte!"],"posts.social_buttons.hackernews":[0,"Debatir en Hacker News"],"footer.diversity_equity_inclusion":[0,"Diversidad, equidad e inclusión"],"footer.critical_infrastructure_defense_project":[0,"Proyecto de protección de infraestructuras críticas"]}]}" ssr="" client="load" opts="{"name":"PostCard","value":true}" await-children="">
En esta publicación del blog, le mostraré cómo utilizar D1 para añadir comentarios a un blog estático. Para ello, crearemos una nueva base de datos D1 y una sencilla API JSON que permita la creación y la recuperación de comentarios...