Astro para desarrolladores de WordPress

En esta página

Astro proporciona las páginas, layouts, componentes y renderizado del servidor para un sitio EmDash. Esta guía cubre los conceptos de Astro utilizados por las plantillas actuales de EmDash. Se asume que ya comprendes los temas de WordPress y las plantillas PHP.

Para funcionalidades del framework que no son específicas de EmDash, usa la documentación de Astro.

Estructura del proyecto

Un sitio Astro asigna a cada tipo de archivo un directorio explícito. Las plantillas actuales de EmDash utilizan esta estructura:

WordPressAstroPropósito
index.php, single.php, page.phpsrc/pages/Rutas URL
template-parts/src/components/Markup reutilizable
header.php y footer.phpsrc/layouts/Estructuras de página compartidas
style.csssrc/styles/Estilos del sitio
Configuración de plugins y base de datosastro.config.mjsIntegraciones y adaptador de servidor
Datos de configuración del temaseed/seed.jsonColecciones, menús y contenido de ejemplo

La plantilla del blog utiliza directorios de rutas que coinciden con sus URLs públicas:

src/
├── components/
│   └── PostCard.astro
├── layouts/
│   └── Base.astro
├── pages/
│   ├── index.astro
│   ├── pages/
│   │   └── [slug].astro
│   └── posts/
│       ├── index.astro
│       └── [slug].astro
└── live.config.ts

Componentes Astro

Un componente .astro combina TypeScript del lado del servidor con una plantilla HTML. El código entre los delimitadores --- se ejecuta en el servidor. El markup debajo del segundo delimitador se convierte en el HTML de respuesta.

El siguiente componente declara props en su frontmatter y los renderiza en su plantilla:

---
interface Props {
  title: string;
  excerpt?: string;
  href: string;
}

const { title, excerpt, href } = Astro.props;
---

<article>
  <h2><a href={href}>{title}</a></h2>
  {excerpt && <p>{excerpt}</p>}
</article>

Astro escapa los valores renderizados con {value}. Las importaciones, consultas a la base de datos y otras operaciones del servidor pertenecen al frontmatter.

Expresiones de plantilla

Las plantillas Astro usan llaves donde una plantilla PHP cambiaría a <?php ?>. Los patrones más comunes en las plantillas EmDash son valores, condiciones y mapeo de arrays:

ObjetivoSintaxis Astro
Imprimir un valor{post.data.title}
Renderizar cuando existe un valor{post.data.excerpt && <p>{post.data.excerpt}</p>}
Elegir entre dos resultados{posts.length === 0 ? <p>Aún no hay publicaciones.</p> : <PostList />}
Renderizar una lista{posts.map((post) => <PostCard title={post.data.title} excerpt={post.data.excerpt} href={"/posts/" + post.id} />)}

La expresión puede usar variables preparadas en el frontmatter, valores de Astro.props o datos devueltos por una consulta EmDash. Astro escapa los valores de cadena por defecto; usa un renderizador como <PortableText /> para texto enriquecido estructurado en lugar de inyectar HTML.

Props y slots

Los props son comparables a los $args pasados a get_template_part(). Hacen que cada entrada sea explícita y pueden ser verificados por TypeScript.

Los slots permiten que un componente padre pase markup a un componente. Un slot por defecto es útil para el contenido de la página, mientras que los slots con nombre proporcionan puntos de inserción adicionales:

---
interface Props {
  title: string;
}

const { title } = Astro.props;
---

<article>
  <h2>{title}</h2>
  <slot />
  <footer><slot name="footer" /></footer>
</article>

La siguiente página llena ambos slots:

---
import Card from "../components/Card.astro";
---

<Card title="Última publicación">
  <p>El contenido principal de la tarjeta.</p>
  <a slot="footer" href="/posts/latest">Leer la publicación</a>
</Card>

Los slots son locales a la llamada del componente. No se comportan como las acciones de WordPress, que pueden recibir callbacks registrados en otro lugar.

Layouts

Un layout posee la estructura de documento compartida que un tema de WordPress a menudo divide entre header.php y footer.php. Las páginas importan el layout y pasan su contenido a través de su slot.

El siguiente layout proporciona una estructura de documento:

---
interface Props {
  title: string;
}

const { title } = Astro.props;
---

<!doctype html>
<html lang="es">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>{title}</title>
  </head>
  <body>
    <header><a href="/">Mi sitio</a></header>
    <main><slot /></main>
  </body>
</html>

La siguiente página proporciona el título y el contenido principal del layout:

---
import Base from "../layouts/Base.astro";
---

<Base title="Inicio">
  <h1>Últimas publicaciones</h1>
</Base>

Enrutamiento basado en archivos

Los archivos en src/pages/ definen rutas. Los nombres de archivo entre corchetes crean segmentos dinámicos.

ArchivoURL
src/pages/index.astro/
src/pages/posts/index.astro/posts
src/pages/posts/[slug].astro/posts/hello-world
src/pages/pages/[slug].astro/pages/about

Dentro de src/pages/posts/[slug].astro, Astro.params.slug contiene el valor de la URL. Lee Enrutamiento de Astro para parámetros rest, redirecciones y otras funcionalidades de enrutamiento.

Renderizado del servidor

Las plantillas actuales de EmDash usan output: "server" en astro.config.mjs. Una página puede por lo tanto consultar la base de datos en cada solicitud, de modo que el contenido publicado no depende de una nueva compilación estática.

No agregues getStaticPaths() a una ruta de tema EmDash a menos que el sitio trate deliberadamente a EmDash como una fuente de datos en tiempo de compilación. Los temas incluidos se renderizan en el servidor.

Lee Renderizado bajo demanda de Astro para el comportamiento a nivel de framework.

Consultar contenido EmDash

EmDash envuelve las colecciones de contenido en vivo de Astro con getEmDashCollection() y getEmDashEntry(). Los resultados de colecciones contienen un array entries. Los resultados de una sola entrada contienen entry, que es null cuando ninguna entrada publicada coincide.

El siguiente archivo usa el mismo ordenamiento e identificadores que la plantilla de blog actual:

---
import { getEmDashCollection } from "emdash";
import Base from "../../layouts/Base.astro";

const { entries: posts, error } = await getEmDashCollection("posts", {
  orderBy: { published_at: "desc" },
});

if (error) {
  return new Response("No se pudieron cargar las publicaciones", { status: 500 });
}
---

<Base title="Publicaciones">
  {posts.map((post) => (
    <article>
      <h2><a href={`/posts/${post.id}`}>{post.data.title}</a></h2>
      {post.data.excerpt && <p>{post.data.excerpt}</p>}
    </article>
  ))}
</Base>

post.id es el identificador de ruta expuesto por Astro y normalmente es el slug de la entrada. post.data.id es el identificador de la base de datos. Usa data.id cuando una API espera el ID de contenido almacenado, como funciones auxiliares de taxonomía o comentarios.

La siguiente ruta dinámica busca una publicación por el slug en la URL y renderiza su campo de Portable Text:

---
import { decodeSlug, getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";
import Base from "../../layouts/Base.astro";

const slug = decodeSlug(Astro.params.slug);
if (!slug) return Astro.redirect("/404");

const { entry: post, error } = await getEmDashEntry("posts", slug);
if (error) return new Response("No se pudo cargar la publicación", { status: 500 });
if (!post) return Astro.redirect("/404");
---

<Base title={post.data.title}>
  <article>
    <h1>{post.data.title}</h1>
    <PortableText value={post.data.content} />
  </article>
</Base>

Continuar con Astro

Las plantillas de EmDash también usan estilos de componentes y pequeños scripts de navegador, pero esas son funcionalidades ordinarias de Astro y no conceptos de EmDash. Lee Estilos y CSS para estilos con alcance y globales, y Scripts y manejo de eventos cuando un componente necesita comportamiento del lado del navegador.