Drupal & Astro
Drupal es una herramienta de gestión de contenido de código abierto.
Prerrequisitos
Sección titulada PrerrequisitosPara comenzar, necesitarás tener lo siguiente:
-
Un proyecto Astro - Si aún no tienes un proyecto Astro, nuestra guía de instalación te pondrá en marcha en poco tiempo.
-
Un sitio Drupal - Si no has configurado un sitio Drupal, puedes seguir las directrices oficiales Instalación de Drupal.
Integración de Drupal con Astro
Sección titulada Integración de Drupal con AstroInstalación del módulo JSON:API de Drupal
Sección titulada Instalación del módulo JSON:API de DrupalPara poder obtener contenido de Drupal, necesitas habilitar el módulo JSON:API de Drupal.
- Navega a la página Extender
admin/modules
a través del menú administrativo Administrar. - Localiza el módulo JSON:API y marca la casilla junto a él.
- Haz clic en Instalar para instalar el nuevo módulo.
Ahora puedes hacer solicitudes GET
a tu aplicación Drupal a través de JSON:API.
Agregar la URL de Drupal en .env
Sección titulada Agregar la URL de Drupal en .envPara agregar tu URL de Drupal a Astro, crea un archivo .env
en la raíz de tu proyecto (si aún no existe) y agrega la siguiente variable:
DRUPAL_BASE_URL="[https://drupal.ddev.site/](https://drupal.ddev.site/)"
Reinicia el servidor de desarrollo para usar esta variable de entorno en tu proyecto Astro.
Configuración de credenciales
Sección titulada Configuración de credencialesDe forma predeterminada, el punto de conexión JSON:API de Drupal es accesible para solicitudes de obtención de datos externas sin requerir autenticación. Esto te permite obtener datos para tu proyecto Astro sin credenciales, pero no permite a los usuarios modificar tus datos o la configuración del sitio.
Sin embargo, si deseas restringir el acceso y requerir autenticación, Drupal proporciona varios métodos de autenticación que incluyen:
- Autenticación básica
- Autenticación basada en clave API
- Autenticación basada en token de acceso/OAuth
- Autenticación basada en token JWT
- Autenticación de token de proveedor de terceros
Puedes agregar tus credenciales a tu archivo .env
.
DRUPAL_BASIC_USERNAME="editor"DRUPAL_BASIC_PASSWORD="editor"DRUPAL_JWT_TOKEN="abc123"...
.env
en Astro.
Tu directorio raíz ahora debería incluir estos nuevos archivos:
- .env
- astro.config.mjs
- package.json
Instalación de dependencias
Sección titulada Instalación de dependenciasLas solicitudes y respuestas JSON:API a menudo pueden ser complejas y estar profundamente anidadas. Para simplificar el trabajo con ellas, puedes usar dos paquetes npm que agilizan tanto las solicitudes como el manejo de respuestas:
JSONA
: Serializador y deserializador de la especificación JSON API v1.0 para usar en el servidor y en el navegador.Drupal JSON-API Params
: Este módulo proporciona una clase auxiliar para crear la consulta requerida. Al hacerlo, también intenta optimizar la consulta utilizando la forma abreviada, siempre que sea posible.
npm install jsona drupal-jsonapi-params
pnpm add jsona drupal-jsonapi-params
yarn add jsona drupal-jsonapi-params
Obtención de datos de Drupal
Sección titulada Obtención de datos de DrupalTu contenido se obtiene de una URL JSON:API.
Estructura de la URL JSON:API de Drupal
Sección titulada Estructura de la URL JSON:API de DrupalLa estructura básica de la URL es: /jsonapi/{entity_type_id}/{bundle_id}
La URL siempre está prefijada por jsonapi
.
- El
entity_type_id
se refiere al Tipo de entidad, como nodo, bloque, usuario, etc. - El
bundle_id
se refiere a los Paquetes de entidad. En el caso de un tipo de entidad Nodo, el paquete podría ser artículo. - En este caso, para obtener la lista de todos los artículos, la URL será
[DRUPAL_BASE_URL]/jsonapi/node/article
.
Para recuperar una entidad individual, la estructura de la URL será /jsonapi/{entity_type_id}/{bundle_id}/{uuid}
, donde uuid es el UUID de la entidad. Por ejemplo, la URL para obtener un artículo específico será de la forma /jsonapi/node/article/2ee9f0ef-1b25-4bbe-a00f-8649c68b1f7e
.
Recuperación de ciertos campos solamente
Sección titulada Recuperación de ciertos campos solamenteRecupera ciertos campos solamente agregando el campo Cadena de consulta a la solicitud.
GET: /jsonapi/{entity_type_id}/{bundle_id}?field[entity_type]=field_list
Ejemplos:
/jsonapi/node/article?fields[node--article]=title,created
/jsonapi/node/article/2ee9f0ef-1b25-4bbe-a00f-8649c68b1f7e?fields[node--article]=title,created,body
Filtrado
Sección titulada FiltradoAgrega un filtro a tu solicitud agregando la Cadena de consulta de filtro.
El filtro más simple y común es un filtro de clave-valor:
GET: /jsonapi/{entity_type_id}/{bundle_id}?filter[field_name]=value&filter[field_other]=value
Ejemplos:
/jsonapi/node/article?filter[title]=Testing JSON:API&filter[status]=1
/jsonapi/node/article/2ee9f0ef-1b25-4bbe-a00f-8649c68b1f7e?fields[node--article]=title&filter[title]=Testing JSON:API
Puedes encontrar más opciones de consulta en la Documentación de JSON:API.
Construcción de una consulta de Drupal
Sección titulada Construcción de una consulta de DrupalLos componentes Astro pueden obtener datos de tu sitio Drupal utilizando el paquete drupal-jsonapi-params
para construir la consulta.
El siguiente ejemplo muestra un componente con una consulta para un tipo de contenido “artículo” que tiene un campo de texto para un título y un campo de texto enriquecido para el contenido:
---import { Jsona } from "jsona";import { DrupalJsonApiParams } from "drupal-jsonapi-params";import type { TJsonApiBody } from "jsona/lib/JsonaTypes";
// Obtener la URL base de Drupalexport const baseUrl: string = import.meta.env.DRUPAL_BASE_URL;
// Generar la consulta JSON:API. Obtener todos los títulos y cuerpos de los artículos publicados.const params: DrupalJsonApiParams = new DrupalJsonApiParams();params.addFields("node--article", ["title", "body"]).addFilter("status", "1");// Genera la cadena de consulta.const path: string = params.getQueryString();const url: string = baseUrl + "/jsonapi/node/article?" + path;
// Obtener los artículosconst request: Response = await fetch(url);const json: string | TJsonApiBody = await request.json();// Iniciar Jsona.const dataFormatter: Jsona = new Jsona();// Deserializar la respuesta.const articles = dataFormatter.deserialize(json);---
<body> { articles?.length ? ( articles.map((article: any) => ( <section> <h2>{article.title}</h2> <article set:html={article.body.value} /> </section> )) ) : ( <div> <h1>No se encontró contenido</h1> </div> ) }</body>
Puedes encontrar más opciones de consulta en la Documentación de JSON:API de Drupal
Creación de un blog con Astro y Drupal
Sección titulada Creación de un blog con Astro y DrupalCon la configuración anterior, ahora puedes crear un blog que use Drupal como CMS.
Prerrequisitos
Sección titulada Prerrequisitos-
Un proyecto Astro con
JSONA
yDrupal JSON-API Params
instalados. -
Un sitio Drupal con al menos una entrada - Para este tutorial, recomendamos comenzar con un nuevo sitio Drupal con instalación estándar.
En la sección Contenido de tu sitio Drupal, crea una nueva entrada haciendo clic en el botón Agregar. Luego, elige Artículo y completa los campos:
- Título:
¡Mi primer artículo para Astro!
- Alias:
/articles/first-article-for astro
- Descripción:
¡Este es mi primer artículo de Astro! ¡Veamos cómo se verá!
Haz clic en Guardar para crear tu primer Artículo. Siéntete libre de agregar tantos artículos como desees.
- Título:
Visualización de una lista de artículos
Sección titulada Visualización de una lista de artículos-
Crea
src/types.ts
si aún no existe y agrega dos nuevas interfaces llamadasDrupalNode
yPath
con el siguiente código. Estas interfaces coincidirán con los campos de tu tipo de contenido de artículo en Drupal y los campos Path. Las usarás para tipar tu respuesta de entradas de artículo.src/types.ts export interface Path {alias: string;pid: number;langcode: string;}export interface DrupalNode extends Record<string, any> {id: string;type: string;langcode: string;status: boolean;drupal_internal__nid: number;drupal_internal__vid: number;changed: string;created: string;title: string;default_langcode: boolean;sticky: boolean;path: Path;}Tu directorio src ahora debería incluir el nuevo archivo:
- .env
- astro.config.mjs
- package.json
Directorysrc/
- types.ts
-
Crea un nuevo archivo llamado
drupal.ts
ensrc/api
y agrega el siguiente código:src/api/drupal.ts import { Jsona } from "jsona";import { DrupalJsonApiParams } from "drupal-jsonapi-params";import type { DrupalNode } from "../types.ts";import type { TJsonApiBody } from "jsona/lib/JsonaTypes";// Obtener la URL base de Drupal.export const baseUrl: string = import.meta.env.DRUPAL_BASE_URL;Esto importará las bibliotecas requeridas, como
Jsona
para deserializar la respuesta,DrupalJsonApiParams
para formatear la URL de la solicitud y los tipos Node y Jsona. También obtendrá elbaseUrl
del archivo.env
.Tu directorio src/api ahora debería incluir el nuevo archivo:
- .env
- astro.config.mjs
- package.json
Directorysrc/
Directoryapi/
- drupal.ts
- types.ts
-
En ese mismo archivo, crea la función
fetchUrl
para realizar la solicitud de obtención y deserializar la respuesta.src/api/drupal.ts import { Jsona } from "jsona";import { DrupalJsonApiParams } from "drupal-jsonapi-params";import type { DrupalNode } from "../types.ts";import type { TJsonApiBody } from "jsona/lib/JsonaTypes";// Obtener la URL base de Drupal.export const baseUrl: string = import.meta.env.DRUPAL_BASE_URL;/*** Obtener url de Drupal.** @param url** @return Promise<TJsonaModel | TJsonaModel[]> como Promise<any>*/export const fetchUrl = async (url: string): Promise<any> => {const request: Response = await fetch(url);const json: string | TJsonApiBody = await request.json();const dataFormatter: Jsona = new Jsona();return dataFormatter.deserialize(json);}; -
Crea la función
getArticles()
para obtener todos los artículos publicados.src/api/drupal.ts import { Jsona } from "jsona";import { DrupalJsonApiParams } from "drupal-jsonapi-params";import type { DrupalNode } from "../types.ts";import type { TJsonApiBody } from "jsona/lib/JsonaTypes";// Obtener la URL base de Drupal.export const baseUrl: string = import.meta.env.DRUPAL_BASE_URL;/*** Obtener url de Drupal.** @param url** @return Promise<TJsonaModel | TJsonaModel[]> como Promise<any>*/export const fetchUrl = async (url: string): Promise<any> => {const request: Response = await fetch(url);const json: string | TJsonApiBody = await request.json();const dataFormatter: Jsona = new Jsona();return dataFormatter.deserialize(json);};/*** Obtener todos los artículos publicados.** @return Promise<DrupalNode[]>*/export const getArticles = async (): Promise<DrupalNode[]> => {const params: DrupalJsonApiParams = new DrupalJsonApiParams();params.addFields("node--article", ["title", "path", "body", "created"]).addFilter("status", "1");const path: string = params.getQueryString();return await fetchUrl(baseUrl + "/jsonapi/node/article?" + path);};Ahora puedes usar la función
getArticles()
en un componente.astro
para obtener todos los artículos publicados con datos para cada título, cuerpo, ruta y fecha de creación. -
Ve a la página Astro donde obtendrás datos de Drupal. El siguiente ejemplo crea una página de inicio de artículos en
src/pages/articles/index.astro
.Importa las dependencias necesarias y obtén todas las entradas de Drupal con un tipo de contenido de
article
usandogetArticles()
, mientras pasas la interfazDrupalNode
para tipar tu respuesta.src/pages/articles/index.astro ---import { Jsona } from "jsona";import { DrupalJsonApiParams } from "drupal-jsonapi-params";import type { TJsonApiBody } from "jsona/lib/JsonaTypes";import type { DrupalNode } from "../../types";import { getArticles } from "../../api/drupal";// Obtener todos los artículos publicados.const articles = await getArticles();---Esta llamada de obtención usando getArticles() devolverá una matriz tipada de entradas que se pueden usar en tu plantilla de página.
Tu directorio
src/pages/
ahora debería incluir el nuevo archivo, si usaste el mismo archivo de página:- .env
- astro.config.mjs
- package.json
Directorysrc/
Directoryapi/
- drupal.ts
Directorypages/
Directoryarticles/
- index.astro
- types.ts
-
Agrega contenido a tu página, como un título. Usa
articles.map()
para mostrar tus entradas de Drupal como elementos de línea en una lista.src/pages/articles/index.astro ---import { Jsona } from "jsona";import { DrupalJsonApiParams } from "drupal-jsonapi-params";import type { TJsonApiBody } from "jsona/lib/JsonaTypes";import type { DrupalNode } from "../types";import { getArticles } from "../api/drupal";// Obtener todos los artículos publicados.const articles = await getArticles();---<html lang="en"><head><title>My news site</title></head><body><h1>My news site</h1><ul>{articles.map((article: DrupalNode) => (<li><a href={article.path.alias.replace("internal:en/", "")}><h2>{article.title}</h2><p>Published on {article.created}</p></a></li>))}</ul></body></html>
Generación de publicaciones de blog individuales
Sección titulada Generación de publicaciones de blog individualesUsa el mismo método para obtener tus datos de Drupal como arriba, pero esta vez, en una página que creará una ruta de página única para cada artículo.
Este ejemplo utiliza el modo estático predeterminado de Astro y crea un archivo de página de enrutamiento dinámico con la función getStaticPaths()
. Esta función se llamará en tiempo de compilación para generar la lista de rutas que se convierten en páginas.
-
Crea un nuevo archivo
src/pages/articles/[path].astro
e importa la interfazDrupalNode
ygetArticle()
desdesrc/api/drupal.ts
. Obtén tus datos dentro de una funcióngetStaticPaths()
para crear rutas para tu blog.src/pages/articles/[path].astro ---import { Jsona } from "jsona";import { DrupalJsonApiParams } from "drupal-jsonapi-params";import type { TJsonApiBody } from "jsona/lib/JsonaTypes";import type { DrupalNode } from "../../types";import { getArticles } from "../../api/drupal";// Obtener todos los artículos publicados.export async function getStaticPaths() {const articles = await getArticles();}---Tu directorio src/pages/articles ahora debería incluir el nuevo archivo:
- .env
- astro.config.mjs
- package.json
Directorysrc/
Directoryapi/
- drupal.ts
Directorypages/
Directoryarticles/
- index.astro
- [path].astro
- types.ts
-
En el mismo archivo, asigna cada entrada de Drupal a un objeto con una propiedad
params
yprops
. La propiedadparams
se utilizará para generar la URL de la página y los valoresprops
se pasarán al componente de la página como props.src/pages/articles/[path].astro ---import { Jsona } from "jsona";import { DrupalJsonApiParams } from "drupal-jsonapi-params";import type { TJsonApiBody } from "jsona/lib/JsonaTypes";import type { DrupalNode } from "../../types";import { getArticles } from "../../api/drupal";// Obtener todos los artículos publicados.export async function getStaticPaths() {const articles = await getArticles();return articles.map((article: DrupalNode) => {return {params: {// Elige `path` para que coincida con el valor de enrutamiento `[path]`path: article.path.alias.split("/")[2],},props: {title: article.title,body: article.body,date: new Date(article.created).toLocaleDateString("es-ES", {day: "numeric",month: "long",year: "numeric",}),},};});}---La propiedad dentro de
params
debe coincidir con el nombre de la ruta dinámica. Dado que el nombre del archivo es[path].astro
, el nombre de la propiedad pasada aparams
debe serpath
.En nuestro ejemplo, el objeto
props
pasa tres propiedades a la página:title
: una cadena, que representa el título de tu publicación.body
: una cadena, que representa el contenido de tu entrada.date
: una marca de tiempo, basada en la fecha de creación de tu archivo.
-
Usa los
props
de la página para mostrar tu publicación de blog.src/pages/articles/[path].astro ---import { Jsona } from "jsona";import { DrupalJsonApiParams } from "drupal-jsonapi-params";import type { TJsonApiBody } from "jsona/lib/JsonaTypes";import type { DrupalNode } from "../../types";import { getArticles } from "../../api/drupal";// Obtener todos los artículos publicados.export async function getStaticPaths() {const articles = await getArticles();return articles.map((article: DrupalNode) => {return {params: {path: article.path.alias.split("/")[2],},props: {title: article.title,body: article.body,date: new Date(article.created).toLocaleDateString("es-ES", {day: "numeric",month: "long",year: "numeric",}),},};});}const { title, date, body } = Astro.props;---<html lang="en"><head><title>{title}</title></head><body><h1>{title}</h1><time>{date}</time><article set:html={body.value} /></body></html> -
Navega a la vista previa de tu servidor de desarrollo y haz clic en una de tus publicaciones para asegurarte de que tu ruta dinámica esté funcionando.
Publicación de tu sitio
Sección titulada Publicación de tu sitioPara desplegar tu sitio web, visita nuestras guías de despliegue y sigue las instrucciones para tu proveedor de alojamiento preferido.
Recursos de la comunidad
Sección titulada Recursos de la comunidadSi encontraste (¡o hiciste!) un video o una publicación de blog útil sobre el uso de Drupal con Astro, agrégalo a esta lista!