API de Contenedor de Astro (experimental)
Añadido en:
astro@4.9.0
La API de Contenedor te permite renderizar componentes de Astro en aislamiento.
Esta API experimental del lado del servidor abre una variedad de posibles usos futuros, pero actualmente está limitada a permitir la comprobación de la salida de componentes de .astro en entornos de vite como vitest.
También te permite cargar manualmente scripts de renderizado para crear contenedores en páginas renderizadas bajo demanda u otros entornos de "shell" fuera de vite (por ejemplo, dentro de una aplicación PHP o Elixir).
Esta API te permite crear un nuevo contenedor y renderizar un componente de Astro devolviendo una cadena o una Response.
Esta API es experimental y está sujeta a cambios decisivos, incluso en versiones menores o de parches. Consulta el CHANGELOG de Astro para ver los cambios a medida que ocurren. Esta página siempre se actualizará con la información más reciente para la última versión de Astro.
create()
Sección titulada “create()”Tipo: (options?: AstroContainerOptions) => Promise<experimental_AstroContainer>
Crea una nueva instancia del contenedor.
import { experimental_AstroContainer } from "astro/container";
const container = await experimental_AstroContainer.create();Acepta un objeto con las siguientes opciones:
export type AstroContainerOptions = { streaming?: boolean; renderers?: AddServerRenderer[];};
export type AddServerRenderer = | { renderer: NamedSSRLoadedRendererValue; name: never; } | { renderer: SSRLoadedRendererValue; name: string; };opción streaming
Sección titulada “opción streaming”Type: boolean
Default: false
Permite renderizar componentes utilizando streaming de HTML.
opción renderers
Sección titulada “opción renderers”Type: AddServerRenderer[]
Default: []
Una lista de renderizadores de cliente cargados que requiere el componente. Usa esto si tu componente .astro renderiza cualquier componente de framework de UI o MDX utilizando una integración oficial de Astro (por ejemplo, React, Vue, etc.).
Los renderizadores se pueden añadir a través de la API de Contenedor automáticamente para aplicaciones estáticas, o casos donde no se llama al contenedor en tiempo de ejecución (por ejemplo, haciendo pruebas con vitest).
Para aplicaciones renderizadas bajo demanda, o casos en los los que se llama al contenedor en tiempo de ejecución o dentro de otros "shells" (por ejemplo, PHP, Ruby, Java, etc.), los renderizadores deben importarse manualmente.
Añadir un renderizador a través de la API de Contenedor
Sección titulada “Añadir un renderizador a través de la API de Contenedor”Para cada integración oficial de Astro, importa y usa la función auxiliar getContainerRenderer() desde su punto de entrada dedicado container-renderer para exponer sus scripts de renderizado de cliente y servidor. Estos puntos de entrada están disponibles para @astrojs/react, @astrojs/preact, @astrojs/solid-js, @astrojs/svelte, @astrojs/vue y @astrojs/mdx.
Para los paquetes de renderizadores fuera de la organización npm @astrojs, busca en su documentación getContainerRenderer() o una función similar proporcionada.
Cuando se usa vite (vitest, integraciones de Astro, etc.), los renderizadores se cargan con la función loadRenderers() desde el módulo virtual astro:container.
Fuera de vite o para uso bajo demanda, tendrás que cargar los renderizadores manualmente.
El siguiente ejemplo proporciona el objeto necesario para renderizar un componente de Astro que renderiza un componente de React y un componente de Svelte:
import { getContainerRenderer as reactContainerRenderer } from "@astrojs/react/container-renderer";import { getContainerRenderer as svelteContainerRenderer } from "@astrojs/svelte/container-renderer";import { loadRenderers } from "astro:container";
const renderers = await loadRenderers([reactContainerRenderer(), svelteContainerRenderer()]);const container = await experimental_AstroContainer.create({ renderers})const result = await container.renderToString(ReactWrapper);Añadir un renderizador manualmente
Sección titulada “Añadir un renderizador manualmente”Cuando se llama al contenedor en tiempo de ejecución, o dentro de otros "shells", las funciones auxiliares del módulo virtual astro:container no están disponibles. Debes importar los renderizadores de servidor y cliente necesarios manualmente y almacenarlos dentro del contenedor usando addServerRenderer y addClientRenderer.
Los renderizadores de servidor son necesarios para construir tu proyecto, y deben almacenarse en el contenedor para cada framework utilizado. Los renderizadores de cliente también son necesarios para hidratar cualquier componente del lado del cliente utilizando directivas client:*.
Solo se necesita una instrucción de importación por framework. Importar un renderizador hace que tanto los renderizadores de servidor como de cliente estén disponibles para tu contenedor. Sin embargo, los renderizadores de servidor deben añadirse a tu contenedor antes que los renderizadores de cliente. Esto permite que todo el contenedor se renderice primero y luego se hidrate cualquier componente interactivo.
El siguiente ejemplo importa manualmente los renderizadores de servidor necesarios para poder mostrar componentes estáticos de Vue y páginas .mdx. Además, añade renderizadores tanto de servidor como de cliente para componentes interactivos de React.
import reactRenderer from "@astrojs/react/server.js";import vueRenderer from "@astrojs/vue/server.js";import mdxRenderer from "@astrojs/mdx/server.js";
const container = await experimental_AstroContainer.create();container.addServerRenderer({ renderer: vueRenderer });container.addServerRenderer({ renderer: mdxRenderer });
container.addServerRenderer({ renderer: reactRenderer });container.addClientRenderer({ name: "@astrojs/react", entrypoint: "@astrojs/react/client.js" });renderToString()
Sección titulada “renderToString()”Tipo: (component: AstroComponentFactory; options?: ContainerRenderOptions) => Promise<string>
Esta función renderiza un componente especificado dentro de un contenedor. Toma un componente de Astro como argumento y devuelve una cadena que representa el HTML/contenido renderizado por el componente de Astro.
import { experimental_AstroContainer } from "astro/container";import Card from "../src/components/Card.astro";
const container = await experimental_AstroContainer.create();const result = await container.renderToString(Card);Bajo el capó, esta función llama a renderToResponse() y a Response.text().
También acepta un objeto como segundo argumento que puede contener una serie de opciones.
renderToResponse()
Sección titulada “renderToResponse()”Tipo: (component: AstroComponentFactory; options?: ContainerRenderOptions) => Promise<Response>
Renderiza un componente y devuelve un objeto Response.
import { experimental_AstroContainer } from "astro/container";import Card from "../src/components/Card.astro";
const container = await experimental_AstroContainer.create();const result = await container.renderToResponse(Card);También acepta un objeto como segundo argumento que puede contener una serie de opciones.
Opciones de renderizado
Sección titulada “Opciones de renderizado”Tanto renderToResponse() como renderToString() aceptan un objeto como segundo argumento:
export type ContainerRenderOptions = { slots?: Record<string, any>; props?: Record<string, unknown>; request?: Request; params?: Record<string, string | undefined>; locals?: App.Locals; routeType?: RouteType; partial?: boolean;};Estos valores opcionales se pueden pasar a la función de renderizado con el fin de proporcionar información adicional necesaria para que un componente de Astro se renderice correctamente.
Type: Record<string, any>
Una opción para pasar contenido a renderizar con <slots>.
Si tu componente de Astro renderiza un slot por defecto, pasa un objeto con default como clave:
import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, { slots: { default: "Some value" }});Si tu componente renderiza slots nombrados, usa los nombres de los slots como las claves del objeto:
------<div> <slot name="header" /> <slot name="footer" /></div>import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, { slots: { header: "Header content", footer: "Footer" }});También puedes renderizar componentes en cascada:
------<div> <slot name="header" /> <slot name="footer" /></div>import Card from "../src/components/Card.astro";import CardHeader from "../src/components/CardHeader.astro";import CardFooter from "../src/components/CardFooter.astro";
const result = await container.renderToString(Card, { slots: { header: await container.renderToString(CardHeader), footer: await container.renderToString(CardFooter) }});opción props
Sección titulada “opción props”Type: Record<string, unknown>
Una opción para pasar propiedades para componentes de Astro.
import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, { props: { name: "Hello, world!" }});---// For TypeScript supportinterface Props { name: string;};
const { name } = Astro.props;---<div> {name}</div>opción request
Sección titulada “opción request”Type: Request
Una opción para pasar una Request con información sobre la ruta/URL que el componente renderizará.
Usa esta opción cuando tu componente necesite leer información como Astro.url o Astro.request.
También puedes inyectar posibles cabeceras o cookies.
import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, { request: new Request("https://example.com/blog", { headers: { "x-some-secret-header": "test-value" } })});opción params
Sección titulada “opción params”Type: Record<string, string | undefined>
Un objeto para pasar información sobre el parámetro de ruta a un componente de Astro responsable de generar rutas dinámicas.
Usa esta opción cuando tu componente necesite un valor para Astro.params para poder generar una sola ruta dinámicamente.
---const { locale, slug } = Astro.params;---<div></div>import LocaleSlug from "../src/components/[locale]/[slug].astro";
const result = await container.renderToString(LocaleSlug, { params: { locale: "en", slug: "getting-started" }});opción locals
Sección titulada “opción locals”Type: App.Locals
Una opción para pasar información de Astro.locals para renderizar tu componente.
Usa esta opción cuando tu componente necesite información almacenada durante el ciclo de vida de una solicitud para poder renderizarse, como el estado de inicio de sesión.
---const { checkAuth } = Astro.locals;const isAuthenticated = checkAuth();---{isAuthenticated ? <span>You're in</span> : <span>You're out</span> }import Card from "../src/components/Card.astro";
test("User is in", async () => { const result = await container.renderToString(Card, { locals: { checkAuth() { return true; } } });
// assert result contains "You're in"});
test("User is out", async () => { const result = await container.renderToString(Card, { locals: { checkAuth() { return false; } } });
// assert result contains "You're out"});opción routeType
Sección titulada “opción routeType”Type: RouteType
Una opción disponible al usar renderToResponse() para especificar que estás renderizando un endpoint:
container.renderToString(Endpoint, { routeType: "endpoint" });import * as Endpoint from "../src/pages/api/endpoint.js";
const response = await container.renderToResponse(Endpoint, { routeType: "endpoint"});const json = await response.json();Para probar tu endpoint en métodos como POST, PATCH, etc., usa la opción request para llamar a la función correcta:
export function GET() {}
// need to test thisexport function POST() {}import * as Endpoint from "../src/pages/api/endpoint.js";
const response = await container.renderToResponse(Endpoint, { routeType: "endpoint", request: new Request("https://example.com", { method: "POST" // Specify POST method for testing })});const json = await response.json();opción partial
Sección titulada “opción partial”Type: boolean
Default: true
astro@4.16.6
Indica si la API de Contenedor renderiza o no los componentes como si fueran parciales de página. El valor por defecto de true renderiza el componente en aislamiento sin una estructura de página completa.
Para renderizar un componente como una página de Astro completa, incluyendo <!DOCTYPE html>, puedes desactivar este comportamiento estableciendo partial en false:
import Blog from "../src/pages/Blog.astro";
const result = await container.renderToString(Card, { partial: false});console.log(result) // includes `<!DOCTYPE html>` at the beginning of the HTML