Aller au contenu

API de l'Adaptateur d'Astro

Astro est conçu pour faciliter le déploiement vers n’importe quel fournisseur de cloud pour le rendu à la demande, également appelé rendu côté serveur (SSR). Cette capacité est fournie par des adaptateurs, qui sont des intégrations. Consultez le guide de rendu à la demande pour apprendre à utiliser un adaptateur existant.

Un adaptateur est un type particulier d’intégration qui fournit un point d’entrée pour le rendu du serveur au moment de la demande. Un adaptateur a deux fonctions :

  • Implémente les API spécifiques à l’hôte pour gérer les requêtes.
  • Configure la compilation en fonction des conventions de l’hôte.

Un adaptateur est une intégration et peut faire tout ce qu’une intégration peut faire.

Un adaptateur doit appeler l’API setAdapter dans le hook astro:config:done comme suit :

my-adapter.mjs
export default function createIntegration() {
return {
name: '@matthewp/my-adapter',
hooks: {
'astro:config:done': ({ setAdapter }) => {
setAdapter({
name: '@matthewp/my-adapter',
serverEntrypoint: '@matthewp/my-adapter/server.js',
supportedAstroFeatures: {
staticOutput: 'stable'
}
});
},
},
};
}

L’objet passé dans setAdapter est défini comme ceci :

interface AstroAdapter {
name: string;
serverEntrypoint?: string;
previewEntrypoint?: string;
exports?: string[];
args?: any;
adapterFeatures?: AstroAdapterFeatures;
supportedAstroFeatures: AstroAdapterFeatureMap;
}
export interface AstroAdapterFeatures {
/**
* Crée une fonction edge qui communiquera avec le middleware Astro.
*/
edgeMiddleware: boolean;
/**
* Détermine le type de sortie de construction pour lequel l'adaptateur est destiné. La valeur par défaut est `server`.
*/
buildOutput?: 'static' | 'server';
}
export type AdapterSupportsKind = 'unsupported' | 'stable' | 'experimental' | 'deprecated' | 'limited';
export type AdapterSupportWithMessage = {
support: Exclude<AdapterSupportsKind, 'stable'>;
message: string;
};
export type AdapterSupport = AdapterSupportsKind | AdapterSupportWithMessage;
export type AstroAdapterFeatureMap = {
/**
* L'adaptateur est capable de servir des pages statiques
*/
staticOutput?: AdapterSupport;
/**
* L'adaptateur est capable de servir des pages statiques ou rendues par le serveur
*/
hybridOutput?: AdapterSupport;
/**
* L'adaptateur est capable de servir des pages rendues à la demande
*/
serverOutput?: AdapterSupport;
/**
* L'adaptateur est capable de prendre en charge les domaines i18n
*/
i18nDomains?: AdapterSupport;
/**
* L'adaptateur est capable de prendre en charge `getSecret` exporté depuis `astro:env/server`
*/
envGetSecret?: AdapterSupport;
/**
* L'adaptateur prend en charge le service d'image Sharp
*/
sharpImageService?: AdapterSupport;
};

Les propriétés sont les suivantes :

  • name : Un nom unique pour votre adaptateur, utilisé pour la journalisation.
  • serverEntrypoint : Le point d’entrée pour le rendu du serveur à la demande.
  • exports : Un tableau d’exportations nommées lorsqu’il est utilisé en conjonction avec createExports (expliqué ci-dessous).
  • adapterFeatures : Un objet qui active des fonctionnalités spécifiques qui doivent être supportées par l’adaptateur. Ces fonctionnalités vont changer la sortie construite, et l’adaptateur doit implémenter la logique appropriée pour gérer la sortie différente.
  • supportedAstroFeatures : Une liste des caractéristiques intégrées d’Astro. Cela permet à Astro de déterminer quelles fonctionnalités un adaptateur ne peut pas ou ne veut pas supporter afin que les messages d’erreur appropriés puissent être fournis.

L’API de l’adaptateur Astro tente de fonctionner avec n’importe quel type d’hôte, et offre un moyen flexible de se conformer aux API de l’hôte.

Certains hôtes sans serveur attendent de vous que vous exportiez une fonction, comme handler :

export function handler(event, context) {
// ...
}

Avec l’API de l’adaptateur, vous y parvenez en implémentant createExports dans votre serverEntrypoint :

import { App } from 'astro/app';
export function createExports(manifest) {
const app = new App(manifest);
const handler = (event, context) => {
// ...
};
return { handler };
}

Ensuite, dans votre intégration, lorsque vous appelez setAdapter, fournissez ce nom dans exports :

my-adapter.mjs
export default function createIntegration() {
return {
name: '@matthewp/my-adapter',
hooks: {
'astro:config:done': ({ setAdapter }) => {
setAdapter({
name: '@matthewp/my-adapter',
serverEntrypoint: '@matthewp/my-adapter/server.js',
exports: ['handler'],
});
},
},
};
}

Certains hôtes attendent que vous démarriez le serveur vous-mêmes, par exemple en écoutant un port. Pour ces types d’hôtes, l’API de l’adaptateur vous permet d’exporter une fonction start qui sera appelée lors de l’exécution du script bundle.

import { App } from 'astro/app';
export function start(manifest) {
const app = new App(manifest);
addEventListener('fetch', event => {
// ...
});
}

Ce module est utilisé pour afficher les pages qui ont été pré-construites par astro build. Astro utilise les objets standards Request et Response. Les hôtes qui ont une API différente pour les requêtes/réponses doivent convertir ces types dans leur adaptateur.

import { App } from 'astro/app';
import http from 'http';
export function start(manifest) {
const app = new App(manifest);
addEventListener('fetch', event => {
event.respondWith(
app.render(event.request)
);
});
}

Les méthodes suivantes sont proposées :

Type : (request: Request, options?: RenderOptions) => Promise<Response>

Cette méthode appelle la page Astro qui correspond à la demande, l’affiche et renvoie une promesse à un objet Response. Cette méthode fonctionne également pour les routes API qui n’affichent pas de pages.

const response = await app.render(request);

Type : {addCookieHeader?: boolean; clientAddress?: string; locals?: object; routeData?: RouteData;}

La méthode app.render() accepte un argument obligatoire request, et un objet optionnel RenderOptions pour addCookieHeader, clientAddress, locals, et routeData.

Type : boolean
Par défaut : false

Ajouter ou non automatiquement tous les cookies écrits par Astro.cookie.set() aux en-têtes de la réponse.

Lorsqu’ils sont définis à true, ils seront ajoutés à l’en-tête Set-Cookie de la réponse sous forme de paires clé-valeur séparées par des virgules. Vous pouvez utiliser l’API standard response.headers.getSetCookie() pour les lire individuellement. Si la valeur est false (par défaut), les cookies ne seront disponibles qu’à partir de App.getSetCookieFromResponse(response).

const response = await app.render(request, { addCookieHeader: true });

Type : string
Par défaut : request[Symbol.for("astro.clientAddress")]

L’adresse IP du client qui sera disponible en tant que Astro.clientAddress dans les pages, et en tant que ctx.clientAddress dans les routes de l’API et le middleware.

L’exemple ci-dessous lit l’en-tête x-forwarded-for et le transmet comme clientAddress. Cette valeur devient disponible pour l’utilisateur en tant que Astro.clientAddress.

const clientAddress = request.headers.get("x-forwarded-for");
const response = await app.render(request, { clientAddress });

Type : object

L’objet context.locals utilisé pour stocker et accéder aux informations pendant le cycle de vie d’une requête.

L’exemple ci-dessous lit un en-tête nommé x-private-header, tente de l’analyser comme un objet et de le passer à locals, qui peut alors être passé à n’importe quelle fonction middleware.

const privateHeader = request.headers.get("x-private-header");
let locals = {};
try {
if (privateHeader) {
locals = JSON.parse(privateHeader);
}
} finally {
const response = await app.render(request, { locals });
}

Type : RouteData
Par défaut : app.match(request)

Fournissez une valeur pour routeData si vous connaissez déjà la route à afficher. Vous éviterez ainsi l’appel interne à app.match pour déterminer la route à afficher.

const routeData = app.match(request);
if (routeData) {
return app.render(request, { routeData });
} else {
/* Réponse 404 spécifique à l'adaptateur */
return new Response(..., { status: 404 });
}

Type : (request: Request) => RouteData | undefined

Cette méthode est utilisée pour déterminer si une demande est conforme aux règles de routage de l’application Astro.

if(app.match(request)) {
const response = await app.render(request);
}

Vous pouvez généralement appeler app.render(request) sans utiliser .match car Astro gère les 404 si vous fournissez un fichier 404.astro. Utilisez app.match(request) si vous voulez gérer les 404 d’une manière différente.

Autoriser l’installation via astro add

Titre de la section Autoriser l’installation via astro add

La commande astro add permet aux utilisateurs d’ajouter facilement des intégrations et des adaptateurs à leur projet. Si vous voulez que votre adaptateur soit installable avec cet outil, ajoutez astro-adapter au champ keywords dans votre package.json :

{
"name": "example",
"keywords": ["astro-adapter"],
}

Une fois que vous avez publié votre adaptateur sur npm, lancer astro add example installera votre paquet avec toutes les dépendances spécifiées dans votre package.json. Nous demanderons également aux utilisateurs de mettre à jour manuellement la configuration de leur projet.

Ajouté à la version : astro@3.0.0

Les fonctionnalités Astro permettent à un adaptateur d’indiquer à Astro s’il est en mesure de prendre en charge une fonctionnalité, ainsi que le niveau de prise en charge de l’adaptateur.

Lors de l’utilisation de ces propriétés, Astro

  • exécute une validation spécifique ;
  • émet des informations contextuelles dans les journaux ;

Ces opérations sont exécutées en fonction des fonctionnalités prises en charge ou non, de leur niveau de prise en charge et de la configuration utilisée par l’utilisateur.

La configuration suivante indique à Astro que cet adaptateur dispose d’un support expérimental pour le service d’image intégré optimisé par Sharp :

my-adapter.mjs
export default function createIntegration() {
return {
name: '@matthewp/my-adapter',
hooks: {
'astro:config:done': ({ setAdapter }) => {
setAdapter({
name: '@matthewp/my-adapter',
serverEntrypoint: '@matthewp/my-adapter/server.js',
supportedAstroFeatures: {
sharpImageService: 'experimental'
}
});
},
},
};
}

Si le service d’image Sharp est utilisé, Astro enregistrera un avertissement et une erreur sur le terminal en fonction de la prise en charge de votre adaptateur :

[@matthewp/my-adapter] The feature is experimental and subject to issues or changes.
[@matthewp/my-adapter] The currently selected adapter `@matthewp/my-adapter` is not compatible with the service "Sharp". Your project will NOT be able to build.

Un message peut également être fourni pour donner plus de contexte à l’utilisateur :

my-adapter.mjs
export default function createIntegration() {
return {
name: '@matthewp/my-adapter',
hooks: {
'astro:config:done': ({ setAdapter }) => {
setAdapter({
name: '@matthewp/my-adapter',
serverEntrypoint: '@matthewp/my-adapter/server.js',
supportedAstroFeatures: {
sharpImageService: {
support: 'limited',
message: 'This adapter has limited support for Sharp, certain features may not work as expected.'
}
}
});
},
},
};
}

Un ensemble de fonctionnalités qui modifient la sortie des fichiers émis. Lorsqu’un adaptateur opte pour ces fonctionnalités, il obtiendra des informations supplémentaires à l’intérieur de hooks spécifiques.

Type : boolean

Définit si un code middleware de rendu à la demande sera regroupé lors de la construction.

Lorsque cette option est activée, elle empêche le code middleware d’être regroupé et importé par toutes les pages pendant la construction :

my-adapter.mjs
export default function createIntegration() {
return {
name: '@matthewp/my-adapter',
hooks: {
'astro:config:done': ({ setAdapter }) => {
setAdapter({
name: '@matthewp/my-adapter',
serverEntrypoint: '@matthewp/my-adapter/server.js',
adapterFeatures: {
edgeMiddleware: true
}
});
},
},
};
}

Ensuite, utilisez le hook astro:build:ssr, qui vous donnera un middlewareEntryPoint, une URL vers le fichier physique sur le système de fichiers.

my-adapter.mjs
export default function createIntegration() {
return {
name: '@matthewp/my-adapter',
hooks: {
'astro:config:done': ({ setAdapter }) => {
setAdapter({
name: '@matthewp/my-adapter',
serverEntrypoint: '@matthewp/my-adapter/server.js',
adapterFeatures: {
edgeMiddleware: true
}
});
},
'astro:build:ssr': ({ middlewareEntryPoint }) => {
// n'oubliez pas de vérifier si cette propriété existe, elle sera `undefined` si l'adaptateur n'accepte pas la fonctionnalité
if (middlewareEntryPoint) {
createEdgeMiddleware(middlewareEntryPoint)
}
}
},
};
}
function createEdgeMiddleware(middlewareEntryPoint) {
// émet un nouveau fichier physique en utilisant votre bundler
}

Type : AdapterSupportsKind

Il s’agit d’une fonctionnalité permettant à votre adaptateur de récupérer les secrets configurés par les utilisateurs dans env.schema.

Activez la fonctionnalité en transmettant toute valeur AdapterSupportsKind valide à l’adaptateur :

my-adapter.mjs
export default function createIntegration() {
return {
name: '@matthewp/my-adapter',
hooks: {
'astro:config:done': ({ setAdapter }) => {
setAdapter({
name: '@matthewp/my-adapter',
serverEntrypoint: '@matthewp/my-adapter/server.js',
adapterFeatures: {
envGetSecret: 'stable'
}
});
},
},
};
}

Le module astro/env/setup vous permet de fournir une implémentation pour getSecret(). Dans le point d’entrée de votre serveur, appelez setGetEnv() dès que possible :

import { App } from 'astro/app';
import { setGetEnv } from "astro/env/setup"
setGetEnv((key) => process.env[key])
export function createExports(manifest) {
const app = new App(manifest);
const handler = (event, context) => {
// ...
};
return { handler };
}

Si vous prenez en charge les secrets, assurez-vous d’appeler setGetEnv() avant getSecret() lorsque vos variables d’environnement sont liées à la requête :

import type { SSRManifest } from 'astro';
import { App } from 'astro/app';
import { setGetEnv } from 'astro/env/setup';
import { createGetEnv } from '../utils/env.js';
type Env = {
[key: string]: unknown;
};
export function createExports(manifest: SSRManifest) {
const app = new App(manifest);
const fetch = async (request: Request, env: Env) => {
setGetEnv(createGetEnv(env));
const response = await app.render(request);
return response;
};
return { default: { fetch } };
}

Type : 'static' | 'server'

Ajouté à la version : astro@5.0.0

Cette propriété vous permet de forcer une forme de sortie spécifique pour la construction. Cela peut être utile pour les adaptateurs qui fonctionnent uniquement avec un type de sortie spécifique, par exemple, votre adaptateur peut s’attendre à un site web statique, mais utilise un adaptateur pour créer des fichiers spécifiques à l’hôte. La valeur par défaut est server si elle n’est pas spécifiée.

my-adapter.mjs
export default function createIntegration() {
return {
name: '@matthewp/my-adapter',
hooks: {
'astro:config:done': ({ setAdapter }) => {
setAdapter({
name: '@matthewp/my-adapter',
serverEntrypoint: '@matthewp/my-adapter/server.js',
adapterFeatures: {
buildOutput: 'static'
}
});
},
},
};
}
Contribuer

Comment pouvons-nous vous aider ?

Créer une issue GitHub

Le moyen le plus rapide d'alerter notre équipe d'un problème.

Communauté