Aller au contenu

Routage

Astro utilise un routage basé sur les fichiers pour générer vos URLs de construction en fonctionde la disposition des fichiers dans le répertoire src/pages/ de votre projet. Lorsqu’un fichier est ajouté au répertoire src/pages de votre projet, il est automatiquement disponible en tant que route basée sur son nom de fichier.

Astro utilise des éléments HTML standard <a> elements pour naviguer entre les itinéraires. Il n’y a pas de composant <Link> spécifique au cadre de travail.

src/pages/index.astro
<p>En savoir plus <a href="/about/">a propos</a> d'Astro!</p>

Les composants Astro (.astro) et les fichiers Markdown (.md) dans le répertoire src/pages deviendront automatiquement des pages de votre site web. La route de chaque page correspond à son chemin et à son nom de fichier dans le répertoire src/pages.

# Exemple: Routes Statiques
src/pages/index.astro -> mysite.com/
src/pages/about.astro -> mysite.com/about
src/pages/about/index.astro -> mysite.com/about
src/pages/about/me.astro -> mysite.com/about/me
src/pages/posts/1.md -> mysite.com/posts/1

Un fichier de page Astro peut spécifier des paramètres de route dynamiques dans son nom de fichier pour générer des 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 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 obtiendront un fichier correspondant. En mode SSR, une page sera générée sur demande pour toute route correspondante.

Parce que toutes les routes doivent être déterminées au moment de la construction, une route dynamique doit exporter une fonction 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 séparées 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().
Méthode associée : Add i18n features (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 à des 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. (Définir le paramètre REST à undefined lui permet de correspondre à la page de premier niveau).

Les paramètres REST peuvent être utilisés avec d’autres paramètres nommés. Par exemple, nous pourrions représenter la visionneuse 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 paramètres nommés suivants :

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

Exemple : Pages dynamiques à plusieurs niveaux

Titre de la section Exemple : Pages dynamiques à plusieurs niveaux

Ici, nous utilisons un paramètre REST ([...slug]) et la fonctionnalité props 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. Comme il ne s’agit pas de routes “statiques”, getStaticPaths ne doit 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

Titre de la section 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 cherchant 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>

Parfois, vous devrez rediriger vos lecteurs vers une nouvelle page, soit de manière permanente parce que la structure de votre site a changé, soit en réponse à une action telle que la connexion à une route authentifiée.

Vous pouvez définir des règles pour rediriger les utilisateurs vers des pages déplacées de façon permanente dans votre configuration Astro. Ou rediriger les utilisateurs dynamiquement au fur et à mesure qu’ils utilisent votre site.

Ajouté à la version : astro@2.9.0

Vous pouvez spécifier une correspondance de redirections permanentes dans votre configuration Astro avec la valeur redirects. Pour la plupart des redirections, il s’agit d’une correspondance entre l’ancienne et la nouvelle route :

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
redirects: {
'/ancienne-page': '/nouvelle-page'
}
});

Ces redirections suivent les mêmes règles que les routes basées sur des fichiers. Les routes dynamiques sont autorisées tant que les nouvelles et les anciennes routes contiennent les mêmes paramètres, par exemple :

{
"/blog/[...slug]": "/articles/[...slug]"
}

En utilisant SSR ou un adaptateur statique, vous pouvez également fournir un objet comme valeur, ce qui vous permet de spécifier le code status en plus de la nouvelle destination :

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
redirects: {
'/ancienne-page': {
status: 302,
destination: '/nouvelle-page'
}
}
});

Lors de l’exécution de astro build, Astro produira des fichiers HTML avec la balise meta refresh par défaut. Les adaptateurs supportés écriront à la place le fichier de configuration de l’hôte avec les redirections.

Le code de statut est 301 par défaut. Si l’on construit des fichiers HTML, le code de statut n’est pas utilisé par le serveur.

Globalement sur Astro, la méthode Astro.redirect vous permet de rediriger vers une autre page dynamiquement. Vous pouvez le faire après avoir vérifié que l’utilisateur est connecté en récupérant sa session à partir d’un cookie.

src/pages/account.astro
---
import { isLoggedIn } from '../utils';
const cookie = Astro.request.headers.get('cookie');
// Si l'utilisateur n'est pas connecté, le rediriger vers la page de connexion.
if (!isLoggedIn(cookie)) {
return Astro.redirect('/login');
}
---
<html>
<!-- Page ici... -->
</html>

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

  • Répertoiresrc/pages/
    • Répertoireposts/
      • 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 selon les règles suivantes :

  • Les routes statiques sans paramètres de chemin sont prioritaires sur toutes les autres routes.
  • Les routes dynamiques utilisant des paramètres nommés sont prioritaires par rapport aux paramètres REST.
  • Les routes dynamiques pré-rendues sont prioritaires sur les routes dynamiques du serveur.
  • Les paramètres REST ont la priorité la plus basse.
  • Les points de terminaison ont toujours la priorité sur les pages.
  • Les égalités sont résolues par ordre alphabétique.

Dans l’exemple ci-dessus, voici quelques exemples de la manière dont les règles feront correspondre une URL demandée à la route utilisée pour construire le code 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

Les redirections suivent également les mêmes règles, mais sont prioritaires en dernier ; s’il existe une route basée sur les fichiers et une redirection avec le même niveau de priorité de route, la route basée sur les fichiers est choisie.

Astro prend en charge la pagination intégrée pour les grandes collections de données qui doivent être divisées en plusieurs pages. Astro génère les propriétés de pagination courantes, y compris les URL des pages précédentes/suivantes, le nombre total de pages, etc.

Les noms des routes paginées doivent utiliser la même syntaxe de [crochets] que les routes dynamiques standard. 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 la page générée.

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

src/pages/astronauts/[page].astro
---
export async function getStaticPaths({ paginate }) {
const astronautPages = [{
astronaut: 'Neil Armstrong',
}, {
astronaut: 'Buzz Aldrin',
}, {
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>

Cela génère les pages suivantes, avec deux éléments par page :

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

Lorsque vous utilisez la fonction paginate(), chaque page reçoit ses données via une propriété page. La propriété page a beaucoup de propriétés utiles, mais voici les principales :

  • page.data - Tableau contenant la portion de données de 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}
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;
};
}

Un cas d’utilisation plus avancé de la pagination est la pagination imbriquée, c’est-à-dire lorsque la pagination est combinée avec d’autres paramètres d’itinéraires dynamiques. Vous pouvez utiliser la pagination imbriquée pour regrouper votre collection paginée en fonction d’une propriété ou d’une balise.

Par exemple, si vous voulez grouper vos posts Markdown paginés par une balise, vous utiliserez la pagination imbriquée en créant une page /src/pages/[tag]/[page].astro qui correspondra aux URLS suivantes :

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

La pagination imbriquée fonctionne en renvoyant un tableau de résultats paginate() de getStaticPaths(), un pour chaque groupe.

Dans l’exemple suivant, nous allons implémenter la pagination imbriquée pour construire les URLs 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 leur nom par 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 dans les pages correspondantes, en les empêchant d’être construits dans des 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.

  • Répertoiresrc/pages/
    • Répertoire_répertoire-caché/
      • page1.md
      • page2.md
    • _page-cachée.astro
    • index.astro
    • Répertoireposts/
      • _SomeComponent.astro
      • _utils.js
      • post1.md