Routage

Astro utilise un routage basé sur les fichiers pour générer les URLs de votre dossier de compilation en fonction des dossiers de votre projet src/pages/. Lorsqu’un fichier est ajouté au dossier src/pages/ de votre projet, une route avec le même nom que ce fichier est alors disponible automatiquement.

Les composants .astro et les fichiers Markdown (.md) dans le dossier src/pages/ deviennent des pages de votre site web. Chaque composant (nommé composant Page) correspond à son chemin et nom dans le dossier src/pages/.

Terminal window
# Exemple: Routes statiques
src/pages/index.astro -> monsite.com/
src/pages/about.astro -> monsite.com/about
src/pages/about/index.astro -> monsite.com/about
src/pages/about/me.astro -> monsite.com/about/me
src/pages/posts/1.md -> monsite.com/posts/1

Astro utilise des éléments HTML<a> standards pour naviguer entre les routes. Il n’y a pas de composant <Link> spécifique au framework fourni.

src/pages/index.astro
<p>Lire d'avantage <a href="/about/">a propos</a> d'Astro!</p>

Un fichier de page Astro peut spécifier des paramètres de route dynamiques dans son nom de fichier pour générer les pages correspondantes. Par exemple, vous pouvez créer un fichier authors/[author].astro qui génère une page de biographie pour chaque auteur de votre blog. author devient un paramètre accessible depuis l’intérieur de la page.

Dans le mode de sortie statique par défaut d’Astro, ces pages sont générées au moment de la construction, et vous devez donc prédéterminer la liste des author qui obtiennent un fichier correspondant. En mode SSR, une page sera générée sur demande pour toute route qui correspond.

Parce que toutes les routes doivent être déterminées au moment de la construction, une route dynamique doit exporter un getStaticPaths() qui renvoie un tableau d’objets avec une propriété params. Chacun de ces objets générera une route correspondante.

[dog].astro définit le paramètre dynamique dog dans son nom de fichier, donc les objets retournés par getStaticPaths() doivent inclure dog dans leurs params. La page peut alors accéder à ce paramètre en utilisant Astro.params.

src/pages/dogs/[dog].astro
---
export function getStaticPaths() {
return [
{params: {dog: 'clifford'}},
{params: {dog: 'rover'}},
{params: {dog: 'spot'}},
];
}
const { dog } = Astro.params;
---
<div>Bon chien, {dog} !</div>

Cela va générer trois pages : /dogs/clifford, /dogs/rover, et /dogs/spot, chacune affichant le nom du chien correspondant.

Le nom du fichier peut inclure plusieurs paramètres, qui doivent tous être inclus dans les objets params de getStaticPaths() :

src/pages/[lang]-[version]/info.astro
---
export function getStaticPaths () {
return [
{params: {lang: 'en', version: 'v1'}},
{params: {lang: 'fr', version: 'v2'}},
];
}
const { lang, version } = Astro.params;
---
...

Cela va générer /en-v1/info et /fr-v2/info.

Les paramètres peuvent être inclus dans des parties distinctes du chemin, ainsi nous pourrions utiliser src/pages/[lang]/[version]/info.astro avec le même getStaticPaths pour générer /en/v1/info et /fr/v2/info.

📚 En savoir plus sur getStaticPaths() (EN).

Si vous avez besoin de plus de flexibilité dans le routage de vos URL, vous pouvez utiliser un paramètre REST ([...path]) dans votre nom de fichier .astro pour correspondre aux chemins de fichiers de n’importe quelle profondeur :

src/pages/sequences/[...path].astro
---
export function getStaticPaths() {
return [
{params: {path: 'one/two/three'}},
{params: {path: 'four'}},
{params: {path: undefined }}
]
}
const { path } = Astro.params;
---
...

Cela générera /sequences/one/two/three, /sequences/four, et /sequences. (Donner au paramètre rest la valeur undefined lui permet de correspondre à la page de niveau principal).

Les paramètres rest peuvent être utilisés avec d’autres paramètres nommés. Par exemple, nous pourrions représenter le visualiseur de fichiers de GitHub avec une route dynamique comme celle-ci :

/[org]/[repo]/tree/[branch]/[...file]

Dans cet exemple, une requête pour /withastro/astro/tree/main/docs/public/favicon.svg serait divisée en les paramètres nommés suivants :

{
org: 'withastro',
repo: 'astro',
branch: 'main',
file: 'docs/public/favicon.svg'
}

Exemple : Pages dynamiques à plusieurs niveaux

Section titled Exemple : Pages dynamiques à plusieurs niveaux

Ici, nous utilisons un paramètre rest ([...slug]) et la fonctionnalité props (EN) de getStaticPaths() pour générer des pages pour des slugs de différentes profondeurs.

src/pages/[...slug].astro
---
export async function getStaticPaths() {
const pages = [
{
slug: undefined,
title: "Magasin Astro",
text: "Bienvenue dans le magasin Astro!",
},
{
slug: "products",
title: "Produits Astro",
text: "Nous avons beaucoup de produits pour vous",
},
{
slug: "products/astro-handbook",
title: "L'ultime manuel d'Astro",
text: "Si vous voulez apprendre Astro, vous devez lire ce livre.",
},
];
return pages.map(({ slug, title, text }) => {
return {
params: { slug },
props: { title, text },
};
});
}
const { title, text } = Astro.props;
---
<html>
<head>
<title>{title}</title>
</head>
<body>
<h1>{title}</h1>
<p>{text}</p>
</body>
</html>

En mode SSR, les routes dynamiques sont définies de la même manière : incluez des crochets [param] ou [...path] dans vos noms de fichiers pour faire correspondre des chaînes ou des chemins arbitraires. Mais comme les routes ne sont plus construites à l’avance, la page sera servie à toute route correspondante. Puisque ce ne sont pas des routes “statiques”, getStaticPaths ne devrait pas être utilisé.

src/pages/resources/[resource]/[id].astro
---
const { resource, id } = Astro.params;
---
<h1>{resource}: {id}</h1>

Cette page sera servie pour toute valeur de resource et id : resources/users/1, resources/colors/blue, etc.

Modification de l’exemple [...slug] pour le mode SSR

Section titled Modification de l’exemple [...slug] pour le mode SSR

Comme les pages SSR ne peuvent pas utiliser getStaticPaths, elles ne peuvent pas recevoir de props. Ici, nous modifions notre exemple précédent pour qu’il fonctionne en SSR en recherchant la valeur du paramètre slug dans un objet. Si la route est à la racine (”/”), le paramètre slug sera undefined. Si la valeur n’existe pas dans l’objet, nous redirigeons vers une page 404.

src/pages/[...slug].astro
---
const pages = [
{
slug: undefined,
title: 'Magasin Astro',
text: 'Bienvenue dans le magasin Astro !',
},
{
slug: 'products',
title: 'Produits Astro',
text: 'Nous avons beaucoup de produits pour vous',
},
{
slug: 'products/astro-handbook',
title: "L'ultime manuel d'Astro",
text: 'Si vous voulez apprendre Astro, vous devez lire ce livre.',
}
];
const { slug } = Astro.params;
const page = pages.find((page) => page.slug === slug);
if (!page) return Astro.redirect("/404");
const { title, text } = page;
---
<html>
<head>
<title>{title}</title>
</head>
<body>
<h1>{title}</h1>
<p>{text}</p>
</body>
</html>

Il est possible que plusieurs routes correspondent au même chemin URL. Par exemple, chacune de ces routes correspondrait à /posts/create :

  • Directorysrc/pages/
    • Directoryposts/
      • create.astro
      • [pid].astro
      • […slug].astro

Astro a besoin de savoir quelle route doit être utilisée pour construire la page. Pour ce faire, il les trie en fonction des règles suivantes :

  • Les routes statiques sans paramètres de chemin d’accès ont la priorité sur toutes les autres routes.
  • Les routes dynamiques utilisant des paramètres nommés sont prioritaires par rapport aux paramètres rest.
  • Les paramètres de repos ont la priorité la plus basse
  • Les égalités sont résolues par ordre alphabétique

Étant donné l’exemple ci-dessus, voici quelques exemples de la façon dont les règles vont faire correspondre une URL demandée à la route utilisée pour construire le HTML :

  • pages/post/create.astro - Correspondra au chemin /post/create
  • pages/post/[pid].astro - Correspondra au chemin /post/1, /post/abc, etc. Mais pas à /post/create
  • pages/post/[...slug].astro - Correspondra au chemin /post/1/2, /post/a/b/c, etc. Mais pas à /post/create, /post/1, /post/abc

Astro supporte la pagination pour les grandes collections de données qui doivent être divisées en plusieurs pages. Astro va générer les propriétés les plus communes de pagination comme l’URL pour page précédente / suivante, le nombre total de pages, etc.

Les noms de routes paginées doivent utiliser la même syntaxe de [crochets] que les routes dynamiques. Par exemple, le nom de fichier /astronauts/[page].astro générera des routes pour /astronauts/1, /astronauts/2, etc, là où [page] est le numéro de pages générées.

Vous pouvez utiliser la fonction paginate() pour générer ces pages pour un tableau de valeurs comme suit :

/src/pages/astronauts/[page].astro
---
export async function getStaticPaths({ paginate }) {
const astronautPages = [{
astronaut: 'Neil Armstrong',
}, {
astronaut: 'Buzz Aldrin',
}, {
astronaut: 'Sally Ride',
}, {
astronaut: 'John Glenn',
}, {
astronaut: 'Jean-Loup Chrétien',
}, {
astronaut: 'Thomas Pesquet',
}];
// Génère des pages à partir de notre tableau d'astronautes, avec 2 par page
return paginate(astronautPages, { pageSize: 2 });
}
// Toutes les données paginées sont passées dans la propriété "page"
const { page } = Astro.props;
---
<!-- Affiche le numéro de la page actuelle. Astro.params.page peut aussi être utilisé ! -->
<h1>Page {page.currentPage}</h1>
<ul>
<!-- Fait la liste de notre tableau d'astronautes -->
{page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>

Ceci va générer les pages suivantes, avec deux éléments par page :

  • /astronauts/1 - Page 1: Affiche “Neil Armstrong” et “Buzz Aldrin”
  • /astronauts/2 - Page 2: Affiche “Sally Ride” et “John Glenn”
  • /astronauts/3 - Page 3: Affiche “Jean-Loup Chrétien” et “Thomas Pesquet”

Lorsque vous utilisez la fonction paginate(), chaque page transmet ses données via une propriété page. La propriété page a pas mal de propriétés utiles, mais voici les plus importantes :

  • page.data - Tableau contenant portion de données de la page que vous avez passé dans la fonction paginate()
  • page.url.next - Lien vers la page suivante dans la collection
  • page.url.prev - Lien vers la page précédente dans la collection
/src/pages/astronauts/[page].astro
---
// Paginons la même liste d'objets { astronaut } que l'exemple précédent
export async function getStaticPaths({ paginate }) { /* ... */ }
const { page } = Astro.props;
---
<h1>Page {page.currentPage}</h1>
<ul>
{page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>
{page.url.prev ? <a href={page.url.prev}>Précédent</a> : null}
{page.url.next ? <a href={page.url.next}>Suivant</a> : null}

Référence Complète de l’API

Section titled Référence Complète de l’API
interface Page<T = any> {
/** Résultat */
data: T[];
/** Métadonnées */
/** Nombre du premier élément de la page, à partir de 0 */
start: number;
/** Nombre du dernier élément de la page, à partir de 0 */
end: number;
/** Nombre total de résultats */
total: number;
/** Numéro de la page actuelle, à partir de 1 */
currentPage: number;
/** Nombre d'éléments par page (par défaut : 25) */
size: number;
/** Nombre de la dernière page */
lastPage: number;
url: {
/** URL de la page actuelle */
current: string;
/** URL de la page précédente (si il y en a une) */
prev: string | undefined;
/** URL de la page suivante (si il y en a une) */
next: string | undefined;
};
}

Une utilisation plus avancée pour la pagination est la pagination imbriquée. Il s’agit du cas où la pagination est combinée avec d’autres paramètres de route dynamique. Vous pouvez utiliser la pagination imbriquée pour grouper votre collection paginée par une propriété ou un tag.

Par exemple, si vous voulez grouper vos articles en Markdown par tag, vous pouvez utiliser la pagination imbriquée en créant une page /src/pages/[tag]/[page].astro qui correspond aux URL suivantes :

  • /red/1 (tag=red)
  • /red/2 (tag=red)
  • /blue/1 (tag=blue)
  • /green/1 (tag=green)

La pagination imbriquée fonctionne en retournant une collection de résultats paginate() depuis getStaticPaths(), une pour chaque groupe.

Dans l’exemple suivant, nous allons implémenter la pagination imbriquée pour construire les URL listées ci-dessus :

/src/pages/[tag]/[page].astro
---
export function getStaticPaths({paginate}) {
const allTags = ['red', 'blue', 'green'];
const allPosts = await Astro.glob('../../posts/*.md');
// Pour chaque tag, retourne un résultat paginate().
// Assurez-vous que vous passez "{params: {tag}}" à la fonction "paginate()"
// Assurez-vous qu'Astro connaît les tags du résultat
return allTags.map((tag) => {
const filteredPosts = allPosts.filter((post) => post.frontmatter.tag === tag);
return paginate(filteredPosts, {
params: { tag },
pageSize: 10
});
});
}
const { page } = Astro.props;
const params = Astro.params;

Vous pouvez exclure des pages, ou même des répertoires entiers de la construction en préfixant leurs noms avec un trait de soulignement (_).

Cela vous permet de créer des pages privées, et aussi de placer les tests, les utilitaires et les composants avec les pages qui leur sont associées, en les empêchant d’être construits en fichiers .html et placés dans le répertoire dist/.

Dans cet exemple, seuls src/pages/index.astro et src/pages/posts/post1.md seront construits comme routes de pages et fichiers HTML.

  • Directorysrc/pages/
    • Directory_répertoire-caché/
      • page1.md
      • page2.md
    • _page-cachée.astro
    • index.astro
    • Directoryposts/
      • _SomeComponent.astro
      • _utils.js
      • post1.md