Aller au contenu

API des conteneurs d'Astro (expérimental)

Ajouté à la version : astro@4.9.0

L’API Conteneur vous permet de restituer les composants Astro de manière isolée.

Cette API expérimentale côté serveur débloque une variété d’utilisations futures potentielles, mais elle est actuellement conçue pour permettre de tester la sortie d’un composant .astro dans les environnements vite tels que vitest.

Elle vous permet également de charger manuellement des scripts de rendu pour créer des conteneurs dans des pages rendues à la demande ou d’autres environnements « shell » en dehors de vite (par exemple, à l’intérieur d’une application PHP ou Elixir).

Cette API vous permet de créer un nouveau conteneur, et de restituer un composant Astro en renvoyant une chaîne de caractères ou un objet Response.

Cette API est expérimentale et sujette à des modifications sans rétrocompatibilité, même dans les versions mineures ou correctives. Veuillez consulter le fichier CHANGELOG d’Astro pour connaître les changements au fur et à mesure qu’ils se produisent. Cette page sera toujours mise à jour avec les informations les plus récentes pour la dernière version d’Astro.

Type : (options?: AstroContainerOptions) => Promise<experimental_AstroContainer>

Crée une nouvelle instance du conteneur.

import { experimental_AstroContainer } from "astro/container";
const container = await experimental_AstroContainer.create();

Elle accepte un objet avec les options suivantes :

export type AstroContainerOptions = {
streaming?: boolean;
renderers?: AddServerRenderer[];
};
export type AddServerRenderer =
| {
renderer: NamedSSRLoadedRendererValue;
name: never;
}
| {
renderer: SSRLoadedRendererValue;
name: string;
};

Type : boolean
Par défaut : false

Active les composants de rendu utilisant le streaming HTML.

Type : AddServerRenderer[]
Par défaut : []

Liste des moteurs de rendu client chargés requis par le composant. Utilisez cette option si votre composant .astro restitue des composants de framework UI ou MDX à l’aide d’une intégration Astro officielle (par exemple React, Vue, etc.).

Les moteurs de rendu peuvent être ajoutés automatiquement via l’API Conteneur pour les applications statiques ou dans les cas où le conteneur n’est pas appelé lors de l’exécution (par exemple, lors de tests avec vitest).

Pour les applications rendues à la demande ou les cas où le conteneur est appelé lors de l’exécution ou à l’intérieur d’autres « shells » (par exemple PHP, Ruby, Java, etc.), les moteurs de rendu doivent être importés manuellement.

Ajout d’un moteur de rendu via l’API Conteneur

Section intitulée « Ajout d’un moteur de rendu via l’API Conteneur »

Pour chaque intégration officielle d’Astro, importez et utilisez la fonction d’aide getContainerRenderer() afin d’exposer ses scripts de rendu client et serveur. Ceux-ci sont disponibles pour @astrojs/react, @astrojs/preact, @astrojs/solid-js, @astrojs/svelte, @astrojs/vue et @astrojs/mdx.

Pour les paquets de rendu en dehors de l’organisation npm @astrojs, consultez leur documentation pour trouver getContainerRenderer() ou une fonction similaire fournie.

Lorsque vous utilisez vite (vitest, des intégrations Astro, etc.), les moteurs de rendu sont chargés avec la fonction loadRenderers() du module virtuel astro:container.

L’exemple suivant fournit l’objet nécessaire pour effectuer le rendu d’un composant Astro qui restitue un composant React et un composant Svelte :

import { getContainerRenderer as reactContainerRenderer } from "@astrojs/react";
import { getContainerRenderer as svelteContainerRenderer } from "@astrojs/svelte";
import { loadRenderers } from "astro:container";
const renderers = await loadRenderers([reactContainerRenderer(), svelteContainerRenderer()]);
const container = await experimental_AstroContainer.create({
renderers
})
const result = await container.renderToString(ReactWrapper);

Lorsque le conteneur est appelé lors de l’exécution ou à l’intérieur d’autres « shells », les fonctions d’aide du module virtuel astro:container ne sont pas disponibles. Vous devez importer manuellement les moteurs de rendu serveur et client nécessaires et les stocker dans le conteneur à l’aide de addServerRenderer et addClientRenderer.

Les moteurs de rendu serveur sont nécessaires pour compiler votre projet et doivent être stockés dans le conteneur pour chaque framework utilisé. Les moteurs de rendu client sont également nécessaires pour hydrater les composants côté client à l’aide des directives client:*.

Une seule instruction d’importation est nécessaire par framework. L’importation d’un moteur de rendu débloque les moteurs de rendu serveur et client pour votre conteneur. Cependant, les moteurs de rendu serveur doivent être ajoutés à votre conteneur avant les moteurs de rendu client. Cela permet à l’ensemble de votre conteneur d’être rendu en premier, puis d’hydrater tous les composants interactifs.

L’exemple suivant importe manuellement les moteurs de rendu serveur nécessaires à l’affichage des composants Vue statiques et des pages .mdx. Il ajoute également les moteurs de rendu serveur et client pour les composants React interactifs.

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" });

Type : (component: AstroComponentFactory; options?: ContainerRenderOptions) => Promise<string>

Cette fonction restitue un composant spécifié à l’intérieur d’un conteneur. Elle prend un composant Astro comme argument et renvoie une chaîne de caractères qui représente le HTML/contenu rendu par le composant 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);

En arrière-plan, cette fonction appelle renderToResponse() et Response.text().

Elle accepte également un objet comme deuxième argument pouvant contenir un certain nombre d’options.

Type : (component: AstroComponentFactory; options?: ContainerRenderOptions) => Promise<Response>

Elle restitue un composant et renvoie un objet 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);

Elle accepte également un objet comme second argument qui peut contenir un nombre d’options.

renderToResponse() et renderToString() acceptent tous deux un objet comme second argument :

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;
};

Ces valeurs optionnelles peuvent être transmises à la fonction de rendu afin de fournir des informations supplémentaires nécessaires au bon rendu d’un composant Astro.

Type : Record<string, any>

Une option pour transmettre du contenu à restituer avec <slots>.

Si votre composant Astro restitue un slot par défaut, transmettez un objet avec default comme nom de propriété :

import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, {
slots: { default: "Some value" }
});

Si votre composant restitue des slots nommés, utilisez les noms de slots en tant que noms de propriété de l’objet :

---
---
<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"
}
});

Vous pouvez également effectuer le rendu des composants en cascade :

---
---
<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)
}
});

Type : Record<string, unknown>

Une option pour transmettre des propriétés aux composants Astro.

import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, {
props: { name: "Hello, world!" }
});
---
// Pour le support TypeScript
interface Props {
name: string;
};
const { name } = Astro.props;
---
<div>
{name}
</div>

Type : Request

Une option pour passer une requête (Request) avec des informations sur le chemin/l’URL que le composant restituera.

Utilisez cette option lorsque votre composant a besoin de lire des informations comme Astro.url ou Astro.request.

Vous pouvez également injecter des en-têtes ou des 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"
}
})
});

Type : Record<string, string | undefined>

Un objet permettant de transmettre des informations liées au chemin à un composant Astro chargé de générer des routes dynamiques.

Utilisez cette option lorsque votre composant a besoin d’une valeur pour Astro.params afin de générer une route unique dynamiquement.

---
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"
}
});

Type : App.Locals

Une option pour passer les informations de Astro.locals pour le rendu de votre composant.

Utilisez cette option lorsque votre composant a besoin d’informations stockées pendant le cycle de vie d’une requête pour effectuer le rendu, comme le statut de connexion.

---
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; }
}
});
// affirmer que le résultat contient « You're in »
});
test("User is out", async () => {
const result = await container.renderToString(Card, {
locals: {
checkAuth() { return false; }
}
});
// affirmer que le résultat contient « You're out »
});

Type : RouteType

Une option disponible lors de l’utilisation de renderToResponse() pour spécifier que vous restituez un point de terminaison :

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();

Pour tester votre point d’accès avec des méthodes telles que POST, PATCH, etc., utilisez l’option request pour appeler la bonne fonction :

export function GET() {}
// doit être testé
export 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" // Spécifier la méthode POST pour les tests
})
});
const json = await response.json();

Type : boolean
Par défaut : true

Ajouté à la version : astro@4.16.6

Si l’API des conteneurs restitue les composants comme s’il s’agissait de pages partielles. C’est généralement le comportement souhaité lors du rendu de components.boolean afin de pouvoir restituer les composants sans une page complète.

Pour restituer un composant sous forme de page Astro complète, incluant <!DOCTYPE html>, vous pouvez désactiver ce comportement en définissant partial sur false :

import Blog from "../src/pages/Blog.astro";
const result = await container.renderToString(Card, {
partial: false
});
console.log(result) // inclut `<!DOCTYPE html>` au début du code HTML
Contribuer Communauté Parrainer